Distributed Autonomous and Networked Control Lab wikidb-distributed-autonomous-and-networked-control-lab https://wikis.ece.iastate.edu/distributed-autonomous-and-networked-control-lab/index.php?title=Main_Page MediaWiki 1.42.1 first-letter Media Special Talk User User talk Distributed Autonomous and Networked Control Lab Distributed Autonomous and Networked Control Lab talk File File talk MediaWiki MediaWiki talk Template Template talk Help Help talk Category Category talk Distributed Autonomous and Networked Control Lab Wiki 0 1 1 2016-03-08T22:05:45Z MediaWiki default 0 wikitext text/x-wiki <big>'''MediaWiki has been successfully installed.'''</big> Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Getting started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] bd962048d95fbb6b6b514885867811db20a5476b 2 1 2016-06-25T18:05:17Z Jnoronha 3 Wiki Home Page wikitext text/x-wiki == <big>'''Distributed Autonomous and Networked Control Lab Wiki'''</big> == Welcome to the Distributed Autonomous and Networked Control Lab Wiki! Here you can find a wealth of information regarding the many projects we have running in the Lab. Below are some of the projects we are working on. ---- ''' == Projects: == ''' [[Crazyflie Swarm]] [[Robotic Agriculture Data Acquisition (RADA)]] [[MicroCART]] [[Camera System and VRPN]] If you can't find what you're looking for please feel free to contribute. Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Getting started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] 23bdc6c3291ff5c2f88388a75c81d49fd2b8b952 3 2 2016-06-25T18:06:11Z Jnoronha 3 wikitext text/x-wiki == <big>'''Distributed Autonomous and Networked Control Lab Wiki'''</big> == Welcome to the Distributed Autonomous and Networked Control Lab Wiki! Here you can find a wealth of information regarding the many projects we have running in the Lab. Below are some of the projects we are working on. ''' == Projects: == ''' [[Crazyflie Swarm]] [[Robotic Agriculture Data Acquisition (RADA)]] [[MicroCART]] [[Camera System and VRPN]] If you can't find what you're looking for please feel free to contribute. Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Getting started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] f659eb5176979c86e59475e17c97e51bd31feb63 8 3 2016-06-25T18:49:21Z Jnoronha 3 [[Main Page]] moved to [[Distributed Autonomous and Networked Control Lab Wiki]]: Renaming the Homepage wikitext text/x-wiki == <big>'''Distributed Autonomous and Networked Control Lab Wiki'''</big> == Welcome to the Distributed Autonomous and Networked Control Lab Wiki! Here you can find a wealth of information regarding the many projects we have running in the Lab. Below are some of the projects we are working on. ''' == Projects: == ''' [[Crazyflie Swarm]] [[Robotic Agriculture Data Acquisition (RADA)]] [[MicroCART]] [[Camera System and VRPN]] If you can't find what you're looking for please feel free to contribute. Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Getting started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] f659eb5176979c86e59475e17c97e51bd31feb63 10 8 2016-06-25T18:50:23Z Jnoronha 3 Removed Initial header since changed main page wikitext text/x-wiki Welcome to the Distributed Autonomous and Networked Control Lab Wiki! Here you can find a wealth of information regarding the many projects we have running in the Lab. Below are some of the projects we are working on. ''' == Projects: == ''' [[Crazyflie Swarm]] [[Robotic Agriculture Data Acquisition (RADA)]] [[MicroCART]] [[Camera System and VRPN]] If you can't find what you're looking for please feel free to contribute. Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Getting started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] 6ca26ba4236dd82ccbb7226525b0ae81ff55ff27 48 10 2016-07-12T16:41:20Z Jnoronha 3 Added colon to 'below are some of the projects...' wikitext text/x-wiki Welcome to the Distributed Autonomous and Networked Control Lab Wiki! Here you can find a wealth of information regarding the many projects we have running in the Lab. Below are some of the projects we are working on: ''' == Projects: == ''' [[Crazyflie Swarm]] [[Robotic Agriculture Data Acquisition (RADA)]] [[MicroCART]] [[Camera System and VRPN]] If you can't find what you're looking for please feel free to contribute. Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Getting started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] 04829c1b139875b5566055386125a413b79de76f Crazyflie Swarm 0 2 4 2016-06-25T18:20:25Z Jnoronha 3 Crazyflie Swarm Home Page wikitext text/x-wiki == <big>'''Crazyflie Swarm '''</big>== The Crazyflie Swarm is a Networked Control platform designed for students to learn more about control and for researchers that wish to apply their research in practice. The platform was started during the Summer of 2015 and continues to be in development. Here you will find descriptions on how the platform works, how you can use it, and how you can get involved in developing the platform further! == Background == The Crazyflie Swarm platform is based off of the ''Crazyflie'' Nano-quadcopter produced and maintained by Bitcraze[https://www.bitcraze.io/]. The ''Crazyflie'' is completely open-source so we are able to look at and modify any part of the code. 6d43a2b39f56d644192965b9ed1fe8a3956d8532 5 4 2016-06-25T18:31:54Z Jnoronha 3 Added client firmware and radio to background, and linked homepage of Bitcraze Wiki wikitext text/x-wiki == <big>'''Crazyflie Swarm '''</big>== The Crazyflie Swarm is a Networked Control platform designed for students to learn more about control and for researchers that wish to apply their research in practice. The platform was started during the Summer of 2015 and continues to be in development. Here you will find descriptions on how the platform works, how you can use it, and how you can get involved in developing the platform further! == Background == The Crazyflie Swarm platform is based off of the ''Crazyflie'' Nano-quadcopter produced and maintained by Bitcraze[https://www.bitcraze.io/]. The ''Crazyflie'' is completely open-source so we are able to look at and modify any part of the code and customize it to our needs. There are 3 components that make up the framework of the Crazyflie platform: *[[PC Client Software]] *[[Firmware]] *[[USB Radio]] == [https://wiki.bitcraze.io/ Bitcraze Wiki] == Bitcraze maintains their own wiki on the many Crazyflie systems. If you can't find what you are looking for here, chances are they will have something to help. 09b82172de16f13cc8a0e492c8898dfe982b8f61 6 5 2016-06-25T18:32:45Z Jnoronha 3 Changed Bitcraze extern link to include full text wikitext text/x-wiki == <big>'''Crazyflie Swarm '''</big>== The Crazyflie Swarm is a Networked Control platform designed for students to learn more about control and for researchers that wish to apply their research in practice. The platform was started during the Summer of 2015 and continues to be in development. Here you will find descriptions on how the platform works, how you can use it, and how you can get involved in developing the platform further! == Background == The Crazyflie Swarm platform is based off of the ''Crazyflie'' Nano-quadcopter produced and maintained by [https://www.bitcraze.io/ Bitcraze]. The ''Crazyflie'' is completely open-source so we are able to look at and modify any part of the code and customize it to our needs. There are 3 components that make up the framework of the Crazyflie platform: *[[PC Client Software]] *[[Firmware]] *[[USB Radio]] == [https://wiki.bitcraze.io/ Bitcraze Wiki] == Bitcraze maintains their own wiki on the many Crazyflie systems. If you can't find what you are looking for here, chances are they will have something to help. d794248507b500bef09efc5e338681597eabed90 7 6 2016-06-25T18:36:33Z Jnoronha 3 Added FAQ page link wikitext text/x-wiki == <big>'''Crazyflie Swarm '''</big>== The Crazyflie Swarm is a Networked Control platform designed for students to learn more about control and for researchers that wish to apply their research in practice. The platform was started during the Summer of 2015 and continues to be in development. Here you will find descriptions on how the platform works, how you can use it, and how you can get involved in developing the platform further! == Background == The Crazyflie Swarm platform is based off of the ''Crazyflie'' Nano-quadcopter produced and maintained by [https://www.bitcraze.io/ Bitcraze]. The ''Crazyflie'' is completely open-source so we are able to look at and modify any part of the code and customize it to our needs. There are 3 components that make up the framework of the Crazyflie platform: *[[PC Client Software]] *[[Firmware]] *[[USB Radio]] == Frequently Asked Questions == For help with common problems and troubleshooting please see the [[FAQ]]. == [https://wiki.bitcraze.io/ Bitcraze Wiki] == Bitcraze maintains their own wiki on the many Crazyflie systems. If you can't find what you are looking for here, chances are they will have something to help. 6fbd8d65c8d5ff0e8d835a6b0a87f811c811ff94 11 7 2016-06-25T18:51:33Z Jnoronha 3 Removed main header (redundant wikitext text/x-wiki The Crazyflie Swarm is a Networked Control platform designed for students to learn more about control and for researchers that wish to apply their research in practice. The platform was started during the Summer of 2015 and continues to be in development. Here you will find descriptions on how the platform works, how you can use it, and how you can get involved in developing the platform further! == Background == The Crazyflie Swarm platform is based off of the ''Crazyflie'' Nano-quadcopter produced and maintained by [https://www.bitcraze.io/ Bitcraze]. The ''Crazyflie'' is completely open-source so we are able to look at and modify any part of the code and customize it to our needs. There are 3 components that make up the framework of the Crazyflie platform: *[[PC Client Software]] *[[Firmware]] *[[USB Radio]] == Frequently Asked Questions == For help with common problems and troubleshooting please see the [[FAQ]]. == [https://wiki.bitcraze.io/ Bitcraze Wiki] == Bitcraze maintains their own wiki on the many Crazyflie systems. If you can't find what you are looking for here, chances are they will have something to help. 810ea5bb057d2f4366105386340c2f3b4e00e9bc 12 11 2016-06-25T19:31:45Z Jnoronha 3 Added 3rd heading major platform components and 2nd heading 'modifying the platform' wikitext text/x-wiki The Crazyflie Swarm is a Networked Control platform designed for students to learn more about control and for researchers that wish to apply their research in practice. The platform was started during the Summer of 2015 and continues to be in development. Here you will find descriptions on how the platform works, how you can use it, and how you can get involved in developing the platform further! == Background == The Crazyflie Swarm platform is based off of the ''Crazyflie'' Nano-quadcopter produced and maintained by [https://www.bitcraze.io/ Bitcraze]. The ''Crazyflie'' is completely open-source so we are able to look at and modify any part of the code and customize it to our needs. ==='''Major Platform Components:'''=== *[[PC Client Software]] *[[Firmware]] *[[USB Radio]] == Modifying the Platform == == Frequently Asked Questions == For help with common problems and troubleshooting please see the [[FAQ]]. == [https://wiki.bitcraze.io/ Bitcraze Wiki] == Bitcraze maintains their own wiki on the many Crazyflie systems. If you can't find what you are looking for here, chances are they will have something to help. 4c5444410a5b11407496db75c92ebf25b359e3e3 13 12 2016-06-25T19:33:27Z Jnoronha 3 slight intro modification wikitext text/x-wiki The Crazyflie Swarm is a Networked Control platform designed for students to learn more about control and for researchers that wish to apply their research in practice. Platform development was started during the Summer of 2015 and continues to this day. Here you will find descriptions on how the platform works, how you can use it, and how you can get involved in developing the platform further! == Background == The Crazyflie Swarm platform is based off of the ''Crazyflie'' Nano-quadcopter produced and maintained by [https://www.bitcraze.io/ Bitcraze]. The ''Crazyflie'' is completely open-source so we are able to look at and modify any part of the code and customize it to our needs. ==='''Major Platform Components:'''=== *[[PC Client Software]] *[[Firmware]] *[[USB Radio]] == Modifying the Platform == == Frequently Asked Questions == For help with common problems and troubleshooting please see the [[FAQ]]. == [https://wiki.bitcraze.io/ Bitcraze Wiki] == Bitcraze maintains their own wiki on the many Crazyflie systems. If you can't find what you are looking for here, chances are they will have something to help. 977cb9c12248b20de98cc1259063ad6613a0fabd 15 13 2016-06-25T19:54:19Z Jnoronha 3 /* Background */ Added High level architecture figure wikitext text/x-wiki The Crazyflie Swarm is a Networked Control platform designed for students to learn more about control and for researchers that wish to apply their research in practice. Platform development was started during the Summer of 2015 and continues to this day. Here you will find descriptions on how the platform works, how you can use it, and how you can get involved in developing the platform further! == Background == The Crazyflie Swarm platform is based off of the ''Crazyflie'' Nano-quadcopter produced and maintained by [https://www.bitcraze.io/ Bitcraze]. The ''Crazyflie'' is completely open-source so we are able to look at and modify any part of the code and customize it to our needs. ==='''Major Platform Components:'''=== [[Image: High_Level_Figure_(Single_Radio_Single_Crazyflie_NO_NUMBERS_CROPPED).jpg‎|thumb|right|A high level overview of the Crazyflie Platform]] *[[PC Client Software]] *[[Firmware]] *[[USB Radio]] == Modifying the Platform == == Frequently Asked Questions == For help with common problems and troubleshooting please see the [[FAQ]]. == [https://wiki.bitcraze.io/ Bitcraze Wiki] == Bitcraze maintains their own wiki on the many Crazyflie systems. If you can't find what you are looking for here, chances are they will have something to help. d705dffa8fc4c16df38ad4e7a1ff35c5af79384c 16 15 2016-06-27T18:28:15Z Jnoronha 3 Added list of topics for modifying the platform (to be filled in) wikitext text/x-wiki The Crazyflie Swarm is a Networked Control platform designed for students to learn more about control and for researchers that wish to apply their research in practice. Platform development was started during the Summer of 2015 and continues to this day. Here you will find descriptions on how the platform works, how you can use it, and how you can get involved in developing the platform further! == Background == The Crazyflie Swarm platform is based off of the ''Crazyflie'' Nano-quadcopter produced and maintained by [https://www.bitcraze.io/ Bitcraze]. The ''Crazyflie'' is completely open-source so we are able to look at and modify any part of the code and customize it to our needs. === Major Platform Components: === [[Image: High_Level_Figure_(Single_Radio_Single_Crazyflie_NO_NUMBERS_CROPPED).jpg‎|thumb|right|A high level overview of the Crazyflie Platform]] *[[PC Client Software]] *[[Firmware]] *[[USB Radio]] == Modifying the Platform == *[[PID Controller]] *[[Logging]] *[[Keyboard Commands]] *[[Radio Channels (Link to Section in USB Radio)]] *[[Flight Modes]] *[[Callbacks]] *[[Adding a Crazyflie]] *[[:Firmware]] == Frequently Asked Questions == For help with common problems and troubleshooting please see the [[FAQ]]. == [https://wiki.bitcraze.io/ Bitcraze Wiki] == Bitcraze maintains their own wiki on the many Crazyflie systems. If you can't find what you are looking for here, chances are they will have something to help. 28056276d7ce0c5f7c4a358193c6a7dfb7098d0d 17 16 2016-06-27T18:36:13Z Jnoronha 3 Changed PID controller topic to more general "Controller" modification wikitext text/x-wiki The Crazyflie Swarm is a Networked Control platform designed for students to learn more about control and for researchers that wish to apply their research in practice. Platform development was started during the Summer of 2015 and continues to this day. Here you will find descriptions on how the platform works, how you can use it, and how you can get involved in developing the platform further! == Background == The Crazyflie Swarm platform is based off of the ''Crazyflie'' Nano-quadcopter produced and maintained by [https://www.bitcraze.io/ Bitcraze]. The ''Crazyflie'' is completely open-source so we are able to look at and modify any part of the code and customize it to our needs. === Major Platform Components: === [[Image: High_Level_Figure_(Single_Radio_Single_Crazyflie_NO_NUMBERS_CROPPED).jpg‎|thumb|right|A high level overview of the Crazyflie Platform]] *[[PC Client Software]] *[[Firmware]] *[[USB Radio]] == Modifying the Platform == *[[Controller]] *[[Logging]] *[[Keyboard Commands]] *[[Radio Channels (Link to Section in USB Radio)]] *[[Flight Modes]] *[[Callbacks]] *[[Adding a Crazyflie]] *[[:Firmware]] == Frequently Asked Questions == For help with common problems and troubleshooting please see the [[FAQ]]. == [https://wiki.bitcraze.io/ Bitcraze Wiki] == Bitcraze maintains their own wiki on the many Crazyflie systems. If you can't find what you are looking for here, chances are they will have something to help. 6c62bb7a962a0c336fc876500c407d0199020e33 Main Page 0 3 9 2016-06-25T18:49:21Z Jnoronha 3 [[Main Page]] moved to [[Distributed Autonomous and Networked Control Lab Wiki]]: Renaming the Homepage wikitext text/x-wiki #REDIRECT [[Distributed Autonomous and Networked Control Lab Wiki]] c68032b4d3ee00c7b348a2dcbe17a466bcdca0c8 File:High Level Figure (Single Radio Single Crazyflie NO NUMBERS CROPPED).jpg 6 4 14 2016-06-25T19:48:10Z Jnoronha 3 High Level Crazyflie System layout wikitext text/x-wiki High Level Crazyflie System layout b73937b5e696ddab6f690bf4dd24d1b591f3e116 Controller 0 5 18 2016-06-27T18:55:05Z Jnoronha 3 Added intro and Subsections for Firmware controllers and Client Controllers wikitext text/x-wiki The Crazyflie platform is completely customizable when it comes to the control design. As long as the controller can be written in C or C++, we can implement it in the Platform. This applies to both the controllers run on the PC Client and the controllers run on the Firmware of the Crazyflie. Below you will find documentation on the different types of Controllers that have been applied to the platform, organized by their location in the Platform. == PC Client == === PID Controller === == Firmware == === PID Controller === a4987e836f450aeddc707c87ecafc49ec855ed87 19 18 2016-06-27T18:59:27Z Jnoronha 3 wikitext text/x-wiki The Crazyflie platform is completely customizable when it comes to the control design. As long as the controller can be written in C or C++, we can implement it in the Platform. This applies to both the controllers run on the PC Client and the controllers run on the Firmware of the Crazyflie. Below you will find documentation on the different types of Controllers that have been applied to the platform, organized by their location in the Platform. == PC Client == === PID Controllers (Position and Yaw) === The first controller implemented on the Client was a PID controller used to stabilize the Crazyflie's position in X, Y, and Z. == Firmware == === PID Controllers (Angular Rotation) === 8d26f22dc9c21bd64fb2b81199966114b7ecaf82 20 19 2016-06-27T19:26:48Z Jnoronha 3 Describing original Firmware Control Architecture wikitext text/x-wiki The Crazyflie platform is completely customizable when it comes to the control design. As long as the controller can be written in C or C++, we can implement it in the Platform. This applies to both the controllers run on the PC Client and the controllers run on the Firmware of the Crazyflie. Originally the only controllers in the Platform were Firmware PID's that controlled the angular position and rates of the Crazyflie for hand flight. The original controller layout can be seen in '''Figure 1'''. Below you will find documentation on the different types of Controllers that have been applied to the platform, organized by their location in the Platform. == PC Client == === PID Controllers (Position and Yaw) === The first controller implemented on the Client was a PID controller used to stabilize the Crazyflie's position in X, Y, and Z. == Firmware == === Original PID Controllers (Angular Rotation) === 509e35341e48b9f5d5331913d59c28460bc5cdf3 USB Radio 0 6 21 2016-07-09T16:58:00Z Jnoronha 3 Page setup and adding basic info wikitext text/x-wiki The USB Radio Dongle acts as the bridge between the Client and the Firmware. It sends control setpoints generated from the Client to the Firmware controllers, as well as receives sensor data from the Firmware to the Client for logging. == Modifying the Radio == The Radio functions can be found in the CCrazyRadio.cpp source file. === Changing Radio Channel === 13e7ccea98d6692b0113cd76da22f7dc0d6ef6de 22 21 2016-07-09T18:24:06Z Jnoronha 3 Added first 3 steps of radio initialization wikitext text/x-wiki The USB Radio Dongle acts as the bridge between the Client and the Firmware. It sends control setpoints generated from the Client to the Firmware controllers, as well as receives sensor data from the Firmware to the Client for logging. == Modifying the Radio == The Radio functions can be found in the [[CCrazyRadio.cpp]] source file. === Radio Initialization === :1. Create CrazyRadio Pointers and Crazyflie Pointers <blockquote> <code> ''CCrazyRadio *crRadio1 = 0;<br/>'' ''CCrazyRadio *crRadio2 = 0;<br/>'' <br/> ''CCrazyflie *cflieCopter1 = 0;''<br/> ''CCrazyflie *cflieCopter2 = 0;''<br/> ''CCrazyflie *cflieCopter3 = 0;''<br/> ''CCrazyflie *cflieCopter4 = 0;''<br/> </code> </blockquote> '''Note:''' You must have a pointer for EACH Radio you want to initialize. :2. Initialize First CrazyRadio <blockquote> <code> crRadio1 = new CCrazyRadio(0); // dongle number (starting at 0)<br/> if( crRadio1->startRadio() ) //assigns pointer to USB location<br/> {<br/> cflieCopter1 = new CCrazyflie(crRadio1, 5); //Assigns Crazyflie1 to Radio1 on Channel 5 <br/> cflieCopter2 = new CCrazyflie(crRadio1, 80); //Assigns Crazyflie2 to Radio1 on Channel 80<br/> }<br/> else <br/> { <br/> std::cerr << "Could not connect to dongle 1. Did you plug it in?" << std::endl; <br/> exit(-1); <br/> } <br/> usleep(10000);<br/> <br/> </code> </blockquote> :3. Initialize Second CrazyRadio (repeat as necessary...) <blockquote> <code> crRadio2 = new CCrazyRadio(1); // dongle number<br/> <br/> if( crRadio2->startRadio() ) <br/> { <br/> cflieCopter3 = new CCrazyflie(crRadio2, 25); <br/> cflieCopter4 = new CCrazyflie(crRadio2, 45); <br/> } <br/> else <br/> { <br/> std::cerr << "Could not connect to dongle 2. Did you plug it in?" << std::endl; <br/> exit(-1); <br/> } <br/> usleep(10000); </code> </blockquote> === Changing Radio Channel === 34af1e3ac8303f240bd5dd3e0d03728f57a85838 23 22 2016-07-09T18:33:22Z Jnoronha 3 Formatted code to have boxes around them wikitext text/x-wiki The USB Radio Dongle acts as the bridge between the Client and the Firmware. It sends control setpoints generated from the Client to the Firmware controllers, as well as receives sensor data from the Firmware to the Client for logging. == Modifying the Radio == The Radio functions can be found in the [[CCrazyRadio.cpp]] source file. === Radio Initialization === :1. Create CrazyRadio Pointers and Crazyflie Pointers <blockquote> <code> <pre>CCrazyRadio *crRadio1 = 0; CCrazyRadio *crRadio2 = 0; CCrazyflie *cflieCopter1 = 0; CCrazyflie *cflieCopter2 = 0; CCrazyflie *cflieCopter3 = 0; CCrazyflie *cflieCopter4 = 0; </pre> </code> </blockquote> '''Note:''' You must have a pointer for EACH Radio you want to initialize. :2. Initialize First CrazyRadio <blockquote> <code> <pre> crRadio1 = new CCrazyRadio(0); // dongle number (starting at 0) if( crRadio1->startRadio() ) //assigns pointer to USB location { cflieCopter1 = new CCrazyflie(crRadio1, 5); //Assigns Crazyflie1 to Radio1 on Channel 5 cflieCopter2 = new CCrazyflie(crRadio1, 80); //Assigns Crazyflie2 to Radio1 on Channel 80 } else { std::cerr << "Could not connect to dongle 1. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :3. Initialize Second CrazyRadio (repeat as necessary...) <blockquote> <code> <pre> crRadio2 = new CCrazyRadio(1); // dongle number if( crRadio2->startRadio() ) { cflieCopter3 = new CCrazyflie(crRadio2, 25); //Assigns Crazyflie3 to Radio2 on Channel 25 cflieCopter4 = new CCrazyflie(crRadio2, 45); //Assigns Crazyflie4 to Radio2 on Channel 45 } else { std::cerr << "Could not connect to dongle 2. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> === Changing Radio Channel === 0ac12629730434286c4814a884623da0b301b234 24 23 2016-07-09T18:42:08Z Jnoronha 3 Finished Radio Initialization Section wikitext text/x-wiki The USB Radio Dongle acts as the bridge between the Client and the Firmware. It sends control setpoints generated from the Client to the Firmware controllers, as well as receives sensor data from the Firmware to the Client for logging. == Modifying the Radio == The Radio functions can be found in the [[CCrazyRadio.cpp]] source file. === Radio Initialization === :1. Create CrazyRadio Pointers and Crazyflie Pointers <blockquote> <code> <pre>CCrazyRadio *crRadio1 = 0; CCrazyRadio *crRadio2 = 0; CCrazyflie *cflieCopter1 = 0; CCrazyflie *cflieCopter2 = 0; CCrazyflie *cflieCopter3 = 0; CCrazyflie *cflieCopter4 = 0; </pre> </code> </blockquote> '''Note:''' You must have a pointer for EACH Radio you want to initialize. :2. Initialize First CrazyRadio <blockquote> <code> <pre> crRadio1 = new CCrazyRadio(0); // dongle number (starting at 0) if( crRadio1->startRadio() ) //assigns pointer to USB location { cflieCopter1 = new CCrazyflie(crRadio1, 5); //Assigns Crazyflie1 to Radio1 on Channel 5 cflieCopter2 = new CCrazyflie(crRadio1, 80); //Assigns Crazyflie2 to Radio1 on Channel 80 } else { std::cerr << "Could not connect to dongle 1. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :3. Initialize Second CrazyRadio (repeat as necessary...) <blockquote> <code> <pre> crRadio2 = new CCrazyRadio(1); // dongle number if( crRadio2->startRadio() ) { cflieCopter3 = new CCrazyflie(crRadio2, 25); //Assigns Crazyflie3 to Radio2 on Channel 25 cflieCopter4 = new CCrazyflie(crRadio2, 45); //Assigns Crazyflie4 to Radio2 on Channel 45 } else { std::cerr << "Could not connect to dongle 2. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :4. (OPTIONAL) Modify Radio Parameters <blockquote> <code> <pre> crRadio1->setARDTime(2000); //Sets Wait Time (in &mu;s) between Packet Retries (**MUST BE IN INCREMENTS OF 250**) crRadio1->setARC(0); //Sets Number of times Retries Packet Send crRadio1->setPower(P_0DBM); //Sets Radio Power (See CCrazyRadio.h for allowed ENUM values) </pre> </code> </blockquote> :5. '''Always''' Delete Radio Pointers Before Ending Program <blockquote> <code> <pre> delete crRadio1; delete crRadio2; </pre> </code> </blockquote> '''Note:''' If you don't delete the pointers then you need to unplug the Radio and plug it back into the USB! === Changing Radio Channel === e37c6947cb34d638877c7777ee666c3d0e2b4051 25 24 2016-07-09T18:43:25Z Jnoronha 3 Removed tabs on delete radio and param modification wikitext text/x-wiki The USB Radio Dongle acts as the bridge between the Client and the Firmware. It sends control setpoints generated from the Client to the Firmware controllers, as well as receives sensor data from the Firmware to the Client for logging. == Modifying the Radio == The Radio functions can be found in the [[CCrazyRadio.cpp]] source file. === Radio Initialization === :1. Create CrazyRadio Pointers and Crazyflie Pointers <blockquote> <code> <pre>CCrazyRadio *crRadio1 = 0; CCrazyRadio *crRadio2 = 0; CCrazyflie *cflieCopter1 = 0; CCrazyflie *cflieCopter2 = 0; CCrazyflie *cflieCopter3 = 0; CCrazyflie *cflieCopter4 = 0; </pre> </code> </blockquote> '''Note:''' You must have a pointer for EACH Radio you want to initialize. :2. Initialize First CrazyRadio <blockquote> <code> <pre> crRadio1 = new CCrazyRadio(0); // dongle number (starting at 0) if( crRadio1->startRadio() ) //assigns pointer to USB location { cflieCopter1 = new CCrazyflie(crRadio1, 5); //Assigns Crazyflie1 to Radio1 on Channel 5 cflieCopter2 = new CCrazyflie(crRadio1, 80); //Assigns Crazyflie2 to Radio1 on Channel 80 } else { std::cerr << "Could not connect to dongle 1. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :3. Initialize Second CrazyRadio (repeat as necessary...) <blockquote> <code> <pre> crRadio2 = new CCrazyRadio(1); // dongle number if( crRadio2->startRadio() ) { cflieCopter3 = new CCrazyflie(crRadio2, 25); //Assigns Crazyflie3 to Radio2 on Channel 25 cflieCopter4 = new CCrazyflie(crRadio2, 45); //Assigns Crazyflie4 to Radio2 on Channel 45 } else { std::cerr << "Could not connect to dongle 2. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :4. (OPTIONAL) Modify Radio Parameters <blockquote> <code> <pre> crRadio1->setARDTime(2000); //Sets Wait Time (in &mu;s) between Packet Retries (**MUST BE IN INCREMENTS OF 250**) crRadio1->setARC(0); //Sets Number of times Retries Packet Send crRadio1->setPower(P_0DBM); //Sets Radio Power (See CCrazyRadio.h for allowed ENUM values) </pre> </code> </blockquote> :5. '''Always''' Delete Radio Pointers Before Ending Program <blockquote> <code> <pre> delete crRadio1; delete crRadio2; </pre> </code> </blockquote> '''Note:''' If you don't delete the pointers then you need to unplug the Radio and plug it back into the USB! === Changing Radio Channel === bc4196fa430a5f9e606d0808c7ecc23ddffee58e 26 25 2016-07-09T18:48:40Z Jnoronha 3 Added brief description to Radio init wikitext text/x-wiki The USB Radio Dongle acts as the bridge between the Client and the Firmware. It sends control setpoints generated from the Client to the Firmware controllers, as well as receives sensor data from the Firmware to the Client for logging. == Modifying the Radio == The Radio functions can be found in the [[CCrazyRadio.cpp]] source file. === Radio Initialization === The following steps are how to Initialize a Radio. This code is currently run at the start of <code> main </code> in [[eris_vrpn.cpp]]. The process below can be extended to '''any number of Radios''' (currently 2 Radios shown) :1. Create CrazyRadio Pointers and Crazyflie Pointers <blockquote> <code> <pre> CCrazyRadio *crRadio1 = 0; CCrazyRadio *crRadio2 = 0; CCrazyflie *cflieCopter1 = 0; CCrazyflie *cflieCopter2 = 0; CCrazyflie *cflieCopter3 = 0; CCrazyflie *cflieCopter4 = 0; </pre> </code> </blockquote> '''Note:''' You must have a pointer for EACH Radio you want to initialize. :2. Initialize First CrazyRadio <blockquote> <code> <pre> crRadio1 = new CCrazyRadio(0); // dongle number (starting at 0) if( crRadio1->startRadio() ) //assigns pointer to USB location { cflieCopter1 = new CCrazyflie(crRadio1, 5); //Assigns Crazyflie1 to Radio1 on Channel 5 cflieCopter2 = new CCrazyflie(crRadio1, 80); //Assigns Crazyflie2 to Radio1 on Channel 80 } else { std::cerr << "Could not connect to dongle 1. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :3. Initialize Second CrazyRadio (repeat as necessary...) <blockquote> <code> <pre> crRadio2 = new CCrazyRadio(1); // dongle number if( crRadio2->startRadio() ) { cflieCopter3 = new CCrazyflie(crRadio2, 25); //Assigns Crazyflie3 to Radio2 on Channel 25 cflieCopter4 = new CCrazyflie(crRadio2, 45); //Assigns Crazyflie4 to Radio2 on Channel 45 } else { std::cerr << "Could not connect to dongle 2. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :4. (OPTIONAL) Modify Radio Parameters <blockquote> <code> <pre> crRadio1->setARDTime(2000); //Sets Wait Time (in &mu;s) between Packet Retries (**MUST BE IN INCREMENTS OF 250**) crRadio1->setARC(0); //Sets Number of times Retries Packet Send crRadio1->setPower(P_0DBM); //Sets Radio Power (See CCrazyRadio.h for allowed ENUM values) </pre> </code> </blockquote> :5. '''Always''' Delete Radio Pointers Before Ending Program <blockquote> <code> <pre> delete crRadio1; delete crRadio2; </pre> </code> </blockquote> '''Note:''' If you don't delete the pointers then you need to unplug the Radio and plug it back into the USB! === Changing Radio Channel === 55cc296855b6fd5798824fa4ea7b471b561b5c52 28 26 2016-07-09T19:44:19Z Jnoronha 3 added low level channel set and description wikitext text/x-wiki The USB Radio Dongle acts as the bridge between the Client and the Firmware. It sends control setpoints generated from the Client to the Firmware controllers, as well as receives sensor data from the Firmware to the Client for logging. == Modifying the Radio == The Radio functions can be found in the [[CCrazyRadio.cpp]] source file. === Radio Initialization === The following steps are how to Initialize a Radio. This code is currently run at the start of <code> main </code> in [[eris_vrpn.cpp]]. The process below can be extended to '''any number of Radios''' (currently 2 Radios shown) :1. Create CrazyRadio Pointers and Crazyflie Pointers <blockquote> <code> <pre> CCrazyRadio *crRadio1 = 0; CCrazyRadio *crRadio2 = 0; CCrazyflie *cflieCopter1 = 0; CCrazyflie *cflieCopter2 = 0; CCrazyflie *cflieCopter3 = 0; CCrazyflie *cflieCopter4 = 0; </pre> </code> </blockquote> '''Note:''' You must have a pointer for EACH Radio you want to initialize. :2. Initialize First CrazyRadio <blockquote> <code> <pre> crRadio1 = new CCrazyRadio(0); // dongle number (starting at 0) if( crRadio1->startRadio() ) //assigns pointer to USB location { cflieCopter1 = new CCrazyflie(crRadio1, 5); //Assigns Crazyflie1 to Radio1 on Channel 5 cflieCopter2 = new CCrazyflie(crRadio1, 80); //Assigns Crazyflie2 to Radio1 on Channel 80 } else { std::cerr << "Could not connect to dongle 1. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :3. Initialize Second CrazyRadio (repeat as necessary...) <blockquote> <code> <pre> crRadio2 = new CCrazyRadio(1); // dongle number if( crRadio2->startRadio() ) { cflieCopter3 = new CCrazyflie(crRadio2, 25); //Assigns Crazyflie3 to Radio2 on Channel 25 cflieCopter4 = new CCrazyflie(crRadio2, 45); //Assigns Crazyflie4 to Radio2 on Channel 45 } else { std::cerr << "Could not connect to dongle 2. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :4. (OPTIONAL) Modify Radio Parameters <blockquote> <code> <pre> crRadio1->setARDTime(2000); //Sets Wait Time (in &mu;s) between Packet Retries (**MUST BE IN INCREMENTS OF 250**) crRadio1->setARC(0); //Sets Number of times Retries Packet Send crRadio1->setPower(P_0DBM); //Sets Radio Power (See CCrazyRadio.h for allowed ENUM values) </pre> </code> </blockquote> :5. '''Always''' Delete Radio Pointers Before Ending Program <blockquote> <code> <pre> delete crRadio1; delete crRadio2; </pre> </code> </blockquote> '''Note:''' If you don't delete the pointers then you need to unplug the Radio and plug it back into the USB! === Changing Radio Channel === Changing the Radio Channel is easy, all you need to do is call the function: <blockquote> <code> <pre> crRadio1->setChannel( cflieCopter1->radioChannel() ); //Sets Radio channel to whatever value cflieCopter1 was assigned (The input can be replaced with a constant if needed) </pre> </code> </blockquote> ==== How does it work? ==== The low level implementation of the <code> setChannel </code> function looks like this: <blockquote> <code> <pre> void CCrazyRadio::setChannel(int nChannel) { if( ALL_THE_DEBUG ) printf( "%s(nChannel:%d)\n", __FUNCTION__, nChannel ); this->writeControl(NULL, 0, 0x01, nChannel, 0); } </pre> </code> </blockquote> Which is using a libusb command <code> writeControl </code> to find the specific USB address of the Radio and write a new Channel to that USB device. The specific values plugged into this function will need to be looked up if you plan on working at this level. e8230704b069d79d326458143d32cc512819c919 29 28 2016-07-09T20:01:32Z Jnoronha 3 Added Directory Footer wikitext text/x-wiki [[Media:Example.ogg]]The USB Radio Dongle acts as the bridge between the Client and the Firmware. It sends control setpoints generated from the Client to the Firmware controllers, as well as receives sensor data from the Firmware to the Client for logging. == Modifying the Radio == The Radio functions can be found in the [[CCrazyRadio.cpp]] source file. === Radio Initialization === The following steps are how to Initialize a Radio. This code is currently run at the start of <code> main </code> in [[eris_vrpn.cpp]]. The process below can be extended to '''any number of Radios''' (currently 2 Radios shown) :1. Create CrazyRadio Pointers and Crazyflie Pointers <blockquote> <code> <pre> CCrazyRadio *crRadio1 = 0; CCrazyRadio *crRadio2 = 0; CCrazyflie *cflieCopter1 = 0; CCrazyflie *cflieCopter2 = 0; CCrazyflie *cflieCopter3 = 0; CCrazyflie *cflieCopter4 = 0; </pre> </code> </blockquote> '''Note:''' You must have a pointer for EACH Radio you want to initialize. :2. Initialize First CrazyRadio <blockquote> <code> <pre> crRadio1 = new CCrazyRadio(0); // dongle number (starting at 0) if( crRadio1->startRadio() ) //assigns pointer to USB location { cflieCopter1 = new CCrazyflie(crRadio1, 5); //Assigns Crazyflie1 to Radio1 on Channel 5 cflieCopter2 = new CCrazyflie(crRadio1, 80); //Assigns Crazyflie2 to Radio1 on Channel 80 } else { std::cerr << "Could not connect to dongle 1. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :3. Initialize Second CrazyRadio (repeat as necessary...) <blockquote> <code> <pre> crRadio2 = new CCrazyRadio(1); // dongle number if( crRadio2->startRadio() ) { cflieCopter3 = new CCrazyflie(crRadio2, 25); //Assigns Crazyflie3 to Radio2 on Channel 25 cflieCopter4 = new CCrazyflie(crRadio2, 45); //Assigns Crazyflie4 to Radio2 on Channel 45 } else { std::cerr << "Could not connect to dongle 2. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :4. (OPTIONAL) Modify Radio Parameters <blockquote> <code> <pre> crRadio1->setARDTime(2000); //Sets Wait Time (in &mu;s) between Packet Retries (**MUST BE IN INCREMENTS OF 250**) crRadio1->setARC(0); //Sets Number of times Retries Packet Send crRadio1->setPower(P_0DBM); //Sets Radio Power (See CCrazyRadio.h for allowed ENUM values) </pre> </code> </blockquote> :5. '''Always''' Delete Radio Pointers Before Ending Program <blockquote> <code> <pre> delete crRadio1; delete crRadio2; </pre> </code> </blockquote> '''Note:''' If you don't delete the pointers then you need to unplug the Radio and plug it back into the USB! === Changing Radio Channel === Changing the Radio Channel is easy, all you need to do is call the function: <blockquote> <code> <pre> crRadio1->setChannel( cflieCopter1->radioChannel() ); //Sets Radio channel to whatever value cflieCopter1 was assigned (The input can be replaced with a constant if needed) </pre> </code> </blockquote> ==== How does it work? ==== The low level implementation of the <code> setChannel </code> function looks like this: <blockquote> <code> <pre> void CCrazyRadio::setChannel(int nChannel) { if( ALL_THE_DEBUG ) printf( "%s(nChannel:%d)\n", __FUNCTION__, nChannel ); this->writeControl(NULL, 0, 0x01, nChannel, 0); } </pre> </code> </blockquote> Which is using a libusb command <code> writeControl </code> to find the specific USB address of the Radio and write a new Channel to that USB device. The specific values plugged into this function will need to be looked up if you plan on working at this level. ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[Firmware]] </center> 7d9e637fb4a0ea1b02f8f813f9d76a884088f7cd 30 29 2016-07-09T20:01:53Z Jnoronha 3 Removed mistaken file link wikitext text/x-wiki The USB Radio Dongle acts as the bridge between the Client and the Firmware. It sends control setpoints generated from the Client to the Firmware controllers, as well as receives sensor data from the Firmware to the Client for logging. == Modifying the Radio == The Radio functions can be found in the [[CCrazyRadio.cpp]] source file. === Radio Initialization === The following steps are how to Initialize a Radio. This code is currently run at the start of <code> main </code> in [[eris_vrpn.cpp]]. The process below can be extended to '''any number of Radios''' (currently 2 Radios shown) :1. Create CrazyRadio Pointers and Crazyflie Pointers <blockquote> <code> <pre> CCrazyRadio *crRadio1 = 0; CCrazyRadio *crRadio2 = 0; CCrazyflie *cflieCopter1 = 0; CCrazyflie *cflieCopter2 = 0; CCrazyflie *cflieCopter3 = 0; CCrazyflie *cflieCopter4 = 0; </pre> </code> </blockquote> '''Note:''' You must have a pointer for EACH Radio you want to initialize. :2. Initialize First CrazyRadio <blockquote> <code> <pre> crRadio1 = new CCrazyRadio(0); // dongle number (starting at 0) if( crRadio1->startRadio() ) //assigns pointer to USB location { cflieCopter1 = new CCrazyflie(crRadio1, 5); //Assigns Crazyflie1 to Radio1 on Channel 5 cflieCopter2 = new CCrazyflie(crRadio1, 80); //Assigns Crazyflie2 to Radio1 on Channel 80 } else { std::cerr << "Could not connect to dongle 1. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :3. Initialize Second CrazyRadio (repeat as necessary...) <blockquote> <code> <pre> crRadio2 = new CCrazyRadio(1); // dongle number if( crRadio2->startRadio() ) { cflieCopter3 = new CCrazyflie(crRadio2, 25); //Assigns Crazyflie3 to Radio2 on Channel 25 cflieCopter4 = new CCrazyflie(crRadio2, 45); //Assigns Crazyflie4 to Radio2 on Channel 45 } else { std::cerr << "Could not connect to dongle 2. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :4. (OPTIONAL) Modify Radio Parameters <blockquote> <code> <pre> crRadio1->setARDTime(2000); //Sets Wait Time (in &mu;s) between Packet Retries (**MUST BE IN INCREMENTS OF 250**) crRadio1->setARC(0); //Sets Number of times Retries Packet Send crRadio1->setPower(P_0DBM); //Sets Radio Power (See CCrazyRadio.h for allowed ENUM values) </pre> </code> </blockquote> :5. '''Always''' Delete Radio Pointers Before Ending Program <blockquote> <code> <pre> delete crRadio1; delete crRadio2; </pre> </code> </blockquote> '''Note:''' If you don't delete the pointers then you need to unplug the Radio and plug it back into the USB! === Changing Radio Channel === Changing the Radio Channel is easy, all you need to do is call the function: <blockquote> <code> <pre> crRadio1->setChannel( cflieCopter1->radioChannel() ); //Sets Radio channel to whatever value cflieCopter1 was assigned (The input can be replaced with a constant if needed) </pre> </code> </blockquote> ==== How does it work? ==== The low level implementation of the <code> setChannel </code> function looks like this: <blockquote> <code> <pre> void CCrazyRadio::setChannel(int nChannel) { if( ALL_THE_DEBUG ) printf( "%s(nChannel:%d)\n", __FUNCTION__, nChannel ); this->writeControl(NULL, 0, 0x01, nChannel, 0); } </pre> </code> </blockquote> Which is using a libusb command <code> writeControl </code> to find the specific USB address of the Radio and write a new Channel to that USB device. The specific values plugged into this function will need to be looked up if you plan on working at this level. ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[Firmware]] </center> c575faf055d0eaad5a4d4ea8c445ea87d7daae43 31 30 2016-07-12T16:12:09Z Jnoronha 3 Added 'how does it work' section to the radio init wikitext text/x-wiki The USB Radio Dongle acts as the bridge between the Client and the Firmware. It sends control setpoints generated from the Client to the Firmware controllers, as well as receives sensor data from the Firmware to the Client for logging. == Modifying the Radio == The Radio functions can be found in the [[CCrazyRadio.cpp]] source file. === Radio Initialization === The following steps are how to Initialize a Radio. This code is currently run at the start of <code> main </code> in [[eris_vrpn.cpp]]. The process below can be extended to '''any number of Radios''' (currently 2 Radios shown) :1. Create CrazyRadio Pointers and Crazyflie Pointers <blockquote> <code> <pre> CCrazyRadio *crRadio1 = 0; CCrazyRadio *crRadio2 = 0; CCrazyflie *cflieCopter1 = 0; CCrazyflie *cflieCopter2 = 0; CCrazyflie *cflieCopter3 = 0; CCrazyflie *cflieCopter4 = 0; </pre> </code> </blockquote> '''Note:''' You must have a pointer for EACH Radio you want to initialize. :2. Initialize First CrazyRadio <blockquote> <code> <pre> crRadio1 = new CCrazyRadio(0); // dongle number (starting at 0) if( crRadio1->startRadio() ) //assigns pointer to USB location { cflieCopter1 = new CCrazyflie(crRadio1, 5); //Assigns Crazyflie1 to Radio1 on Channel 5 cflieCopter2 = new CCrazyflie(crRadio1, 80); //Assigns Crazyflie2 to Radio1 on Channel 80 } else { std::cerr << "Could not connect to dongle 1. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :3. Initialize Second CrazyRadio (repeat as necessary...) <blockquote> <code> <pre> crRadio2 = new CCrazyRadio(1); // dongle number if( crRadio2->startRadio() ) { cflieCopter3 = new CCrazyflie(crRadio2, 25); //Assigns Crazyflie3 to Radio2 on Channel 25 cflieCopter4 = new CCrazyflie(crRadio2, 45); //Assigns Crazyflie4 to Radio2 on Channel 45 } else { std::cerr << "Could not connect to dongle 2. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :4. (OPTIONAL) Modify Radio Parameters <blockquote> <code> <pre> crRadio1->setARDTime(2000); //Sets Wait Time (in &mu;s) between Packet Retries (**MUST BE IN INCREMENTS OF 250**) crRadio1->setARC(0); //Sets Number of times Retries Packet Send crRadio1->setPower(P_0DBM); //Sets Radio Power (See CCrazyRadio.h for allowed ENUM values) </pre> </code> </blockquote> :5. '''Always''' Delete Radio Pointers Before Ending Program <blockquote> <code> <pre> delete crRadio1; delete crRadio2; </pre> </code> </blockquote> '''Note:''' If you don't delete the pointers then you need to unplug the Radio and plug it back into the USB! ====How does it work?==== The Radio initialization was originally only able to support a single Radio per computer and a single Crazyflie per Radio. This was a result of how the <code> openUSBDongle() </code> function was written. === Changing Radio Channel === Changing the Radio Channel is easy, all you need to do is call the function: <blockquote> <code> <pre> crRadio1->setChannel( cflieCopter1->radioChannel() ); //Sets Radio channel to whatever value cflieCopter1 was assigned (The input can be replaced with a constant if needed) </pre> </code> </blockquote> ==== How does it work? ==== The low level implementation of the <code> setChannel </code> function looks like this: <blockquote> <code> <pre> void CCrazyRadio::setChannel(int nChannel) { if( ALL_THE_DEBUG ) printf( "%s(nChannel:%d)\n", __FUNCTION__, nChannel ); this->writeControl(NULL, 0, 0x01, nChannel, 0); } </pre> </code> </blockquote> Which is using a libusb command <code> writeControl </code> to find the specific USB address of the Radio and write a new Channel to that USB device. The specific values plugged into this function will need to be looked up if you plan on working at this level. ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[Firmware]] </center> f25af661ab0be75c83fe77c11d1b7bd9bb72fa17 49 31 2016-07-12T17:22:52Z Jnoronha 3 Added images to radio init how does it work wikitext text/x-wiki The USB Radio Dongle acts as the bridge between the Client and the Firmware. It sends control setpoints generated from the Client to the Firmware controllers, as well as receives sensor data from the Firmware to the Client for logging. == Modifying the Radio == The Radio functions can be found in the [[CCrazyRadio.cpp]] source file. === Radio Initialization === The following steps are how to Initialize a Radio. This code is currently run at the start of <code> main </code> in [[eris_vrpn.cpp]]. The process below can be extended to '''any number of Radios''' (currently 2 Radios shown) :1. Create CrazyRadio Pointers and Crazyflie Pointers <blockquote> <code> <pre> CCrazyRadio *crRadio1 = 0; CCrazyRadio *crRadio2 = 0; CCrazyflie *cflieCopter1 = 0; CCrazyflie *cflieCopter2 = 0; CCrazyflie *cflieCopter3 = 0; CCrazyflie *cflieCopter4 = 0; </pre> </code> </blockquote> '''Note:''' You must have a pointer for EACH Radio you want to initialize. :2. Initialize First CrazyRadio <blockquote> <code> <pre> crRadio1 = new CCrazyRadio(0); // dongle number (starting at 0) if( crRadio1->startRadio() ) //assigns pointer to USB location { cflieCopter1 = new CCrazyflie(crRadio1, 5); //Assigns Crazyflie1 to Radio1 on Channel 5 cflieCopter2 = new CCrazyflie(crRadio1, 80); //Assigns Crazyflie2 to Radio1 on Channel 80 } else { std::cerr << "Could not connect to dongle 1. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :3. Initialize Second CrazyRadio (repeat as necessary...) <blockquote> <code> <pre> crRadio2 = new CCrazyRadio(1); // dongle number if( crRadio2->startRadio() ) { cflieCopter3 = new CCrazyflie(crRadio2, 25); //Assigns Crazyflie3 to Radio2 on Channel 25 cflieCopter4 = new CCrazyflie(crRadio2, 45); //Assigns Crazyflie4 to Radio2 on Channel 45 } else { std::cerr << "Could not connect to dongle 2. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :4. (OPTIONAL) Modify Radio Parameters <blockquote> <code> <pre> crRadio1->setARDTime(2000); //Sets Wait Time (in &mu;s) between Packet Retries (**MUST BE IN INCREMENTS OF 250**) crRadio1->setARC(0); //Sets Number of times Retries Packet Send crRadio1->setPower(P_0DBM); //Sets Radio Power (See CCrazyRadio.h for allowed ENUM values) </pre> </code> </blockquote> :5. '''Always''' Delete Radio Pointers Before Ending Program <blockquote> <code> <pre> delete crRadio1; delete crRadio2; </pre> </code> </blockquote> '''Note:''' If you don't delete the pointers then you need to unplug the Radio and plug it back into the USB! ====How does it work?==== The Radio initialization was originally only able to support a single Radio per computer and a single Crazyflie per Radio. This was a result of how the <code> openUSBDongle() </code> function was written. Orignially the code worked as follows: [[Image:RadioSelectionORIGINAL.png]] The issue with this is that if you want to assign another Radio it will always point to the same USB address, thus the different Radio pointers <code> crRadio1 </code> and <code> crRadio2 </code> would point to the same Radio dongle. So we modified the <code> openUSBDongle() </code> to take in the number of Radios you want to start, and then initialize them as follows: [[Image:RadioSelectionMULTIRADIO.png]] === Changing Radio Channel === Changing the Radio Channel is easy, all you need to do is call the function: <blockquote> <code> <pre> crRadio1->setChannel( cflieCopter1->radioChannel() ); //Sets Radio channel to whatever value cflieCopter1 was assigned (The input can be replaced with a constant if needed) </pre> </code> </blockquote> ==== How does it work? ==== The low level implementation of the <code> setChannel </code> function looks like this: <blockquote> <code> <pre> void CCrazyRadio::setChannel(int nChannel) { if( ALL_THE_DEBUG ) printf( "%s(nChannel:%d)\n", __FUNCTION__, nChannel ); this->writeControl(NULL, 0, 0x01, nChannel, 0); } </pre> </code> </blockquote> Which is using a libusb command <code> writeControl </code> to find the specific USB address of the Radio and write a new Channel to that USB device. The specific values plugged into this function will need to be looked up if you plan on working at this level. ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[Firmware]] </center> 33bdff400988c1f6b52dfc59d29343ece78f1e35 50 49 2016-07-12T17:23:37Z Jnoronha 3 spelling mistake wikitext text/x-wiki The USB Radio Dongle acts as the bridge between the Client and the Firmware. It sends control setpoints generated from the Client to the Firmware controllers, as well as receives sensor data from the Firmware to the Client for logging. == Modifying the Radio == The Radio functions can be found in the [[CCrazyRadio.cpp]] source file. === Radio Initialization === The following steps are how to Initialize a Radio. This code is currently run at the start of <code> main </code> in [[eris_vrpn.cpp]]. The process below can be extended to '''any number of Radios''' (currently 2 Radios shown) :1. Create CrazyRadio Pointers and Crazyflie Pointers <blockquote> <code> <pre> CCrazyRadio *crRadio1 = 0; CCrazyRadio *crRadio2 = 0; CCrazyflie *cflieCopter1 = 0; CCrazyflie *cflieCopter2 = 0; CCrazyflie *cflieCopter3 = 0; CCrazyflie *cflieCopter4 = 0; </pre> </code> </blockquote> '''Note:''' You must have a pointer for EACH Radio you want to initialize. :2. Initialize First CrazyRadio <blockquote> <code> <pre> crRadio1 = new CCrazyRadio(0); // dongle number (starting at 0) if( crRadio1->startRadio() ) //assigns pointer to USB location { cflieCopter1 = new CCrazyflie(crRadio1, 5); //Assigns Crazyflie1 to Radio1 on Channel 5 cflieCopter2 = new CCrazyflie(crRadio1, 80); //Assigns Crazyflie2 to Radio1 on Channel 80 } else { std::cerr << "Could not connect to dongle 1. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :3. Initialize Second CrazyRadio (repeat as necessary...) <blockquote> <code> <pre> crRadio2 = new CCrazyRadio(1); // dongle number if( crRadio2->startRadio() ) { cflieCopter3 = new CCrazyflie(crRadio2, 25); //Assigns Crazyflie3 to Radio2 on Channel 25 cflieCopter4 = new CCrazyflie(crRadio2, 45); //Assigns Crazyflie4 to Radio2 on Channel 45 } else { std::cerr << "Could not connect to dongle 2. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :4. (OPTIONAL) Modify Radio Parameters <blockquote> <code> <pre> crRadio1->setARDTime(2000); //Sets Wait Time (in &mu;s) between Packet Retries (**MUST BE IN INCREMENTS OF 250**) crRadio1->setARC(0); //Sets Number of times Retries Packet Send crRadio1->setPower(P_0DBM); //Sets Radio Power (See CCrazyRadio.h for allowed ENUM values) </pre> </code> </blockquote> :5. '''Always''' Delete Radio Pointers Before Ending Program <blockquote> <code> <pre> delete crRadio1; delete crRadio2; </pre> </code> </blockquote> '''Note:''' If you don't delete the pointers then you need to unplug the Radio and plug it back into the USB! ====How does it work?==== The Radio initialization was originally only able to support a single Radio per computer and a single Crazyflie per Radio. This was a result of how the <code> openUSBDongle() </code> function was written. Originally the code worked as follows: [[Image:RadioSelectionORIGINAL.png]] The issue with this is that if you want to assign another Radio it will always point to the same USB address, thus the different Radio pointers <code> crRadio1 </code> and <code> crRadio2 </code> would point to the same Radio dongle. So we modified the <code> openUSBDongle() </code> to take in the number of Radios you want to start, and then initialize them as follows: [[Image:RadioSelectionMULTIRADIO.png]] === Changing Radio Channel === Changing the Radio Channel is easy, all you need to do is call the function: <blockquote> <code> <pre> crRadio1->setChannel( cflieCopter1->radioChannel() ); //Sets Radio channel to whatever value cflieCopter1 was assigned (The input can be replaced with a constant if needed) </pre> </code> </blockquote> ==== How does it work? ==== The low level implementation of the <code> setChannel </code> function looks like this: <blockquote> <code> <pre> void CCrazyRadio::setChannel(int nChannel) { if( ALL_THE_DEBUG ) printf( "%s(nChannel:%d)\n", __FUNCTION__, nChannel ); this->writeControl(NULL, 0, 0x01, nChannel, 0); } </pre> </code> </blockquote> Which is using a libusb command <code> writeControl </code> to find the specific USB address of the Radio and write a new Channel to that USB device. The specific values plugged into this function will need to be looked up if you plan on working at this level. ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[Firmware]] </center> f0a4c33169fcb648ee228c0191a98f357f441a58 Eris vrpn.cpp 0 7 27 2016-07-09T18:54:04Z Jnoronha 3 Set up framework for codebase wikitext text/x-wiki This is the C code for the mainloop of the Crazyflie Swarm Platform (as of 7/9/2016). '''Please update this with new changes.''' <blockquote> <code> <pre> ***INSERT CODE*** </pre> </code> </blockquote> 2161e1e4b01b33b97264c13aa280bbb3e3d38963 File:RadioSelectionMULTIRADIO.png 6 8 32 2016-07-12T16:12:51Z Jnoronha 3 Flow chart of Multi-Radio Initialization wikitext text/x-wiki Flow chart of Multi-Radio Initialization 28320075626fd572c74f87c4d1ed33860d2d5eef File:RadioSelectionORIGINAL.png 6 9 33 2016-07-12T16:14:23Z Jnoronha 3 Flow chart of the Original Radio Initialization process. wikitext text/x-wiki Flow chart of the Original Radio Initialization process. ed17336d08641cf8267b2c2734173df29fdec7ef File:Keyboard Input.png 6 10 34 2016-07-12T16:15:02Z Jnoronha 3 Flow chart of the Keyboard Input sub-routine wikitext text/x-wiki Flow chart of the Keyboard Input sub-routine b4ea53f4359ccfe92050fb077a2e3d6e1d2f2a08 File:LandingMode.png 6 11 35 2016-07-12T16:16:07Z Jnoronha 3 Flow chart of the LANDING flight mode. wikitext text/x-wiki Flow chart of the LANDING flight mode. 7f466e2a065d69f2e64d885d32a606671d13161a File:VRPNGO.png 6 12 36 2016-07-12T16:17:12Z Jnoronha 3 Flow Chart of the platform's main loop. wikitext text/x-wiki Flow Chart of the platform's main loop. 346a1f38528078d81a904aa3bb5c70886fe93576 File:YawSync.png 6 13 37 2016-07-12T16:18:29Z Jnoronha 3 Flow Chart of the Yaw synchronization sub-routine. wikitext text/x-wiki Flow Chart of the Yaw synchronization sub-routine. 22c53518ef747216c95cf3ba580da0e2a7a96706 File:VRPN INIT.png 6 14 38 2016-07-12T16:19:27Z Jnoronha 3 Flow chart of the Connection initialization to VRPN. wikitext text/x-wiki Flow chart of the Connection initialization to VRPN. 43e8b620aa2e802eb203b7ae4a731747212fdee6 File:RequestLogDataPacketEx.png 6 15 39 2016-07-12T16:20:30Z Jnoronha 3 Communications packet Diagram example of Logging Data sent from the Crazyflie to the Client wikitext text/x-wiki Communications packet Diagram example of Logging Data sent from the Crazyflie to the Client b88a15e61391ddb1dbb91d2a45e15f54336c2aef File:FirmwareOnlyPIDArchitecture.png 6 16 40 2016-07-12T16:22:56Z Jnoronha 3 Block diagram of the Angular Rate and Angular Position PID's located on the Crazyflie Firmware. wikitext text/x-wiki Block diagram of the Angular Rate and Angular Position PID's located on the Crazyflie Firmware. 34061a4dd79f6ee4d1cab6ebf296bc85d51ee2ed File:CompletePIDArchitectureFigure.png 6 17 41 2016-07-12T16:24:08Z Jnoronha 3 Block diagram of the entire Platform's PID architecture. (4 PID's located on the Client, and 5 PID's located on the Firmware) wikitext text/x-wiki Block diagram of the entire Platform's PID architecture. (4 PID's located on the Client, and 5 PID's located on the Firmware) 1e6d7fd474efcb599846242b725db9ba3accac0e File:Camera9Figure.jpg 6 18 42 2016-07-12T16:26:27Z Jnoronha 3 Photo of the OptiTrack motion capture camera system. (Cameras 7, 8, 9) wikitext text/x-wiki Photo of the OptiTrack motion capture camera system. (Cameras 7, 8, 9) f36c3fa881fcdb5c008d77084b5b06b6bcac5e5a File:MultiRadioMultiCrazyflie.jpg 6 19 43 2016-07-12T16:29:01Z Jnoronha 3 High level architecture of the Multi-Radio Multi-Crazyflie (single Crazyflie per Radio) configuration. wikitext text/x-wiki High level architecture of the Multi-Radio Multi-Crazyflie (single Crazyflie per Radio) configuration. cb3a74d6f8a12688c646e044420ee68537ef811a File:SingleRadioMultiCrazyflie.jpg 6 20 44 2016-07-12T16:32:01Z Jnoronha 3 High level architecture of the Single-Radio Multi-Crazyflie platform configuration. wikitext text/x-wiki High level architecture of the Single-Radio Multi-Crazyflie platform configuration. d4dcc2417fe0c802dacc05a3c175a13af66a041f File:3spheres.png 6 21 45 2016-07-12T16:35:47Z Jnoronha 3 Figure of the Intersection of 3 Spheres for solving Trilateration problem. (Source: https://en.wikipedia.org/wiki/Trilateration#/media/File:3spheres.svg) wikitext text/x-wiki Figure of the Intersection of 3 Spheres for solving Trilateration problem. (Source: https://en.wikipedia.org/wiki/Trilateration#/media/File:3spheres.svg) 7df4cc3e23bf2f9934d34d490013a4345761e3b6 File:DefaultCrazyflieGUIMainScreen.JPG 6 22 46 2016-07-12T16:37:02Z Jnoronha 3 Screenshot of the Crazyflie GUI running on the Bitcraze Virtual Machine. wikitext text/x-wiki Screenshot of the Crazyflie GUI running on the Bitcraze Virtual Machine. 3f0833d93b7d61b6c60ffcc76ef3f0fa0ec9401e File:DefaultCrazyflieGUIBootloader.JPG 6 23 47 2016-07-12T16:38:02Z Jnoronha 3 Screenshot of the Crazyflie Bootloader User Interface. wikitext text/x-wiki Screenshot of the Crazyflie Bootloader User Interface. 9414da3f61ffe8574ac5f9b79654f2f8294c89b3 File:RadioSelectionOldToNew.png 6 24 51 2016-07-12T17:24:24Z Jnoronha 3 Flow chart comparison of the Original Radio init to the Modified Radio init. wikitext text/x-wiki Flow chart comparison of the Original Radio init to the Modified Radio init. 11b3c83bbf7c657b47394fca92ebf32dd52808f1 52 51 2016-07-12T17:31:28Z Jnoronha 3 uploaded a new version of "[[Image:RadioSelectionOldToNew.png]]": Flow Chart comparison of the Original Radio init to the new Multi-Radio Init. wikitext text/x-wiki Flow chart comparison of the Original Radio init to the Modified Radio init. 11b3c83bbf7c657b47394fca92ebf32dd52808f1 USB Radio 0 6 53 50 2016-07-12T17:33:32Z Jnoronha 3 Combined Radio Init images into one OldToNew image wikitext text/x-wiki The USB Radio Dongle acts as the bridge between the Client and the Firmware. It sends control setpoints generated from the Client to the Firmware controllers, as well as receives sensor data from the Firmware to the Client for logging. == Modifying the Radio == The Radio functions can be found in the [[CCrazyRadio.cpp]] source file. === Radio Initialization === The following steps are how to Initialize a Radio. This code is currently run at the start of <code> main </code> in [[eris_vrpn.cpp]]. The process below can be extended to '''any number of Radios''' (currently 2 Radios shown) :1. Create CrazyRadio Pointers and Crazyflie Pointers <blockquote> <code> <pre> CCrazyRadio *crRadio1 = 0; CCrazyRadio *crRadio2 = 0; CCrazyflie *cflieCopter1 = 0; CCrazyflie *cflieCopter2 = 0; CCrazyflie *cflieCopter3 = 0; CCrazyflie *cflieCopter4 = 0; </pre> </code> </blockquote> '''Note:''' You must have a pointer for EACH Radio you want to initialize. :2. Initialize First CrazyRadio <blockquote> <code> <pre> crRadio1 = new CCrazyRadio(0); // dongle number (starting at 0) if( crRadio1->startRadio() ) //assigns pointer to USB location { cflieCopter1 = new CCrazyflie(crRadio1, 5); //Assigns Crazyflie1 to Radio1 on Channel 5 cflieCopter2 = new CCrazyflie(crRadio1, 80); //Assigns Crazyflie2 to Radio1 on Channel 80 } else { std::cerr << "Could not connect to dongle 1. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :3. Initialize Second CrazyRadio (repeat as necessary...) <blockquote> <code> <pre> crRadio2 = new CCrazyRadio(1); // dongle number if( crRadio2->startRadio() ) { cflieCopter3 = new CCrazyflie(crRadio2, 25); //Assigns Crazyflie3 to Radio2 on Channel 25 cflieCopter4 = new CCrazyflie(crRadio2, 45); //Assigns Crazyflie4 to Radio2 on Channel 45 } else { std::cerr << "Could not connect to dongle 2. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :4. (OPTIONAL) Modify Radio Parameters <blockquote> <code> <pre> crRadio1->setARDTime(2000); //Sets Wait Time (in &mu;s) between Packet Retries (**MUST BE IN INCREMENTS OF 250**) crRadio1->setARC(0); //Sets Number of times Retries Packet Send crRadio1->setPower(P_0DBM); //Sets Radio Power (See CCrazyRadio.h for allowed ENUM values) </pre> </code> </blockquote> :5. '''Always''' Delete Radio Pointers Before Ending Program <blockquote> <code> <pre> delete crRadio1; delete crRadio2; </pre> </code> </blockquote> '''Note:''' If you don't delete the pointers then you need to unplug the Radio and plug it back into the USB! ====How does it work?==== The Radio initialization was originally only able to support a single Radio per computer and a single Crazyflie per Radio. This was a result of how the <code> openUSBDongle() </code> function was written. Originally the code worked as follows: [[Image:RadioSelectionOldToNew.png]] The issue with this is that if you want to assign another Radio it will always point to the same USB address, thus the different Radio pointers <code> crRadio1 </code> and <code> crRadio2 </code> would point to the same Radio dongle. So we modified the <code> openUSBDongle() </code> to take in the number of Radios you want to start, and then initialize them with a loop. === Changing Radio Channel === Changing the Radio Channel is easy, all you need to do is call the function: <blockquote> <code> <pre> crRadio1->setChannel( cflieCopter1->radioChannel() ); //Sets Radio channel to whatever value cflieCopter1 was assigned (The input can be replaced with a constant if needed) </pre> </code> </blockquote> ==== How does it work? ==== The low level implementation of the <code> setChannel </code> function looks like this: <blockquote> <code> <pre> void CCrazyRadio::setChannel(int nChannel) { if( ALL_THE_DEBUG ) printf( "%s(nChannel:%d)\n", __FUNCTION__, nChannel ); this->writeControl(NULL, 0, 0x01, nChannel, 0); } </pre> </code> </blockquote> Which is using a libusb command <code> writeControl </code> to find the specific USB address of the Radio and write a new Channel to that USB device. The specific values plugged into this function will need to be looked up if you plan on working at this level. ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[Firmware]] </center> 7b6c72950a94a2b240cae0de4382df51d7fffc6d 57 53 2016-07-12T18:08:31Z Jnoronha 3 Updated Navigation Bar wikitext text/x-wiki The USB Radio Dongle acts as the bridge between the Client and the Firmware. It sends control setpoints generated from the Client to the Firmware controllers, as well as receives sensor data from the Firmware to the Client for logging. == Modifying the Radio == The Radio functions can be found in the [[CCrazyRadio.cpp]] source file. === Radio Initialization === The following steps are how to Initialize a Radio. This code is currently run at the start of <code> main </code> in [[eris_vrpn.cpp]]. The process below can be extended to '''any number of Radios''' (currently 2 Radios shown) :1. Create CrazyRadio Pointers and Crazyflie Pointers <blockquote> <code> <pre> CCrazyRadio *crRadio1 = 0; CCrazyRadio *crRadio2 = 0; CCrazyflie *cflieCopter1 = 0; CCrazyflie *cflieCopter2 = 0; CCrazyflie *cflieCopter3 = 0; CCrazyflie *cflieCopter4 = 0; </pre> </code> </blockquote> '''Note:''' You must have a pointer for EACH Radio you want to initialize. :2. Initialize First CrazyRadio <blockquote> <code> <pre> crRadio1 = new CCrazyRadio(0); // dongle number (starting at 0) if( crRadio1->startRadio() ) //assigns pointer to USB location { cflieCopter1 = new CCrazyflie(crRadio1, 5); //Assigns Crazyflie1 to Radio1 on Channel 5 cflieCopter2 = new CCrazyflie(crRadio1, 80); //Assigns Crazyflie2 to Radio1 on Channel 80 } else { std::cerr << "Could not connect to dongle 1. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :3. Initialize Second CrazyRadio (repeat as necessary...) <blockquote> <code> <pre> crRadio2 = new CCrazyRadio(1); // dongle number if( crRadio2->startRadio() ) { cflieCopter3 = new CCrazyflie(crRadio2, 25); //Assigns Crazyflie3 to Radio2 on Channel 25 cflieCopter4 = new CCrazyflie(crRadio2, 45); //Assigns Crazyflie4 to Radio2 on Channel 45 } else { std::cerr << "Could not connect to dongle 2. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :4. (OPTIONAL) Modify Radio Parameters <blockquote> <code> <pre> crRadio1->setARDTime(2000); //Sets Wait Time (in &mu;s) between Packet Retries (**MUST BE IN INCREMENTS OF 250**) crRadio1->setARC(0); //Sets Number of times Retries Packet Send crRadio1->setPower(P_0DBM); //Sets Radio Power (See CCrazyRadio.h for allowed ENUM values) </pre> </code> </blockquote> :5. '''Always''' Delete Radio Pointers Before Ending Program <blockquote> <code> <pre> delete crRadio1; delete crRadio2; </pre> </code> </blockquote> '''Note:''' If you don't delete the pointers then you need to unplug the Radio and plug it back into the USB! ====How does it work?==== The Radio initialization was originally only able to support a single Radio per computer and a single Crazyflie per Radio. This was a result of how the <code> openUSBDongle() </code> function was written. Originally the code worked as follows: [[Image:RadioSelectionOldToNew.png]] The issue with this is that if you want to assign another Radio it will always point to the same USB address, thus the different Radio pointers <code> crRadio1 </code> and <code> crRadio2 </code> would point to the same Radio dongle. So we modified the <code> openUSBDongle() </code> to take in the number of Radios you want to start, and then initialize them with a loop. === Changing Radio Channel === Changing the Radio Channel is easy, all you need to do is call the function: <blockquote> <code> <pre> crRadio1->setChannel( cflieCopter1->radioChannel() ); //Sets Radio channel to whatever value cflieCopter1 was assigned (The input can be replaced with a constant if needed) </pre> </code> </blockquote> ==== How does it work? ==== The low level implementation of the <code> setChannel </code> function looks like this: <blockquote> <code> <pre> void CCrazyRadio::setChannel(int nChannel) { if( ALL_THE_DEBUG ) printf( "%s(nChannel:%d)\n", __FUNCTION__, nChannel ); this->writeControl(NULL, 0, 0x01, nChannel, 0); } </pre> </code> </blockquote> Which is using a libusb command <code> writeControl </code> to find the specific USB address of the Radio and write a new Channel to that USB device. The specific values plugged into this function will need to be looked up if you plan on working at this level. ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] </center> 254174b43e84ee47e683bae4077a18b76f0066c3 PC Client Software 0 25 54 2016-07-12T17:54:24Z Jnoronha 3 Added the introduction and section headers wikitext text/x-wiki The PC Client software comes in many forms. The out-of-the-box Client is written in Python and has a Graphical User Interface (GUI). The GUI is well suited for beginners, but can only support a single Radio and a single Crazyflie at a time. The easiest way to start out is with the [https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze Virtual Machine (VM)], which comes with all the files and dependencies pre-installed and can run on any computer (Windows, Mac, Linux, etc.). For more advanced users who want to use the swarm capabilities of our platform will have to use the Client we developed in C and C++. ==Bitcraze VM== ==Swarm Client== Our Client is programmed in C and C++. 530bc8258eea8a9b81d6efac1d007f30494547b6 55 54 2016-07-12T18:05:29Z Jnoronha 3 Added VM disclaimer wikitext text/x-wiki The PC Client software comes in many forms. The out-of-the-box Client is written in Python and has a Graphical User Interface (GUI). The GUI is well suited for beginners, but can only support a single Radio and a single Crazyflie at a time. The easiest way to start out is with the [https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze Virtual Machine (VM)], which comes with all the files and dependencies pre-installed and can run on any computer (Windows, Mac, Linux, etc.). For more advanced users who want to use the swarm capabilities of our platform will have to use the Client we developed in C and C++. ==[https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze VM]== ('''Note:''' The VM is updated frequently so the information below may be different than the current VM) ==Swarm Client== Our Client is programmed in C and C++. 2b5dbf398a114e35b2e2e34cf65a31cfde348906 56 55 2016-07-12T18:07:38Z Jnoronha 3 Added navigation bar wikitext text/x-wiki The PC Client software comes in many forms. The out-of-the-box Client is written in Python and has a Graphical User Interface (GUI). The GUI is well suited for beginners, but can only support a single Radio and a single Crazyflie at a time. The easiest way to start out is with the [https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze Virtual Machine (VM)], which comes with all the files and dependencies pre-installed and can run on any computer (Windows, Mac, Linux, etc.). For more advanced users who want to use the swarm capabilities of our platform will have to use the Client we developed in C and C++. ==[https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze VM]== ('''Note:''' The VM is updated frequently so the information below may be different than the current VM) ==Swarm Client== Our Client is programmed in C and C++. ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] </center> 0c6d9b6e4a3abe51543b6ba351938c1128474904 59 56 2016-07-12T19:57:06Z Jnoronha 3 Added VM tutorials from Bitcraze Wiki wikitext text/x-wiki The PC Client software comes in many forms. The out-of-the-box Client is written in Python and has a Graphical User Interface (GUI). The GUI is well suited for beginners, but can only support a single Radio and a single Crazyflie at a time. The easiest way to start out is with the [https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze Virtual Machine (VM)], which comes with all the files and dependencies pre-installed and can run on any computer (Windows, Mac, Linux, etc.). For more advanced users who want to use the swarm capabilities of our platform will have to use the Client we developed in C and C++. ==[https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze VM]== ('''Note:''' The VM is updated frequently so the information below may be different than the current VM) The Bitcraze wiki has a tutorial on [https://wiki.bitcraze.io/projects:virtualmachine:tutorials:vmware-win7 installing the VM]. Along with another tutorial on how to get started [https://www.bitcraze.io/getting-started-with-development/ using the VM]. These are both very simple starting guides that will help you become familiar with the VM. ==Swarm Client== The swarm Client is a re-creation of the Original Client but programmed in C and C++. ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] </center> eaca70cba21fd4985fd91bf4af6e228772d7929a 79 59 2016-07-18T20:23:23Z Jnoronha 3 Added intro to VM Client wikitext text/x-wiki The PC Client software comes in many forms. The out-of-the-box Client is written in Python and has a Graphical User Interface (GUI). The GUI is well suited for beginners, but can only support a single Radio and a single Crazyflie at a time. The easiest way to start out is with the [https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze Virtual Machine (VM)], which comes with all the files and dependencies pre-installed and can run on any computer (Windows, Mac, Linux, etc.). For more advanced users who want to use the swarm capabilities of our platform will have to use the [[#Swarm Client|Swarm Client]] we developed in C and C++. ==[https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze VM]== ('''Note:''' The VM is updated frequently so the information below may be different than the current VM) The Bitcraze wiki has a tutorial on [https://wiki.bitcraze.io/projects:virtualmachine:tutorials:vmware-win7 installing the VM]. Along with another tutorial on how to get started [https://www.bitcraze.io/getting-started-with-development/ using the VM]. These are both very simple starting guides that will help you become familiar with the VM. ===Crazyflie Client GUI=== On the VM you can find the Crazyflie Client Graphical User Interface (GUI). To run the Client you want to open a terminal and navigate to <code>projects/''''FIND PATH''''</code> and then run the command <code>sudo ./bin/cfclient</code> (Alternatively, you can use the desktop to navigate to the folder and open a terminal there) Once you do that you should see something similar to this: [[Image:DefaultCrazyflieGUIMainScreen.JPG|500px]] This is the main screen of the Client GUI and there are many tabs and features that you can access directly from this screen. The most important parts of this screen are the following: #Connect Button #Bootloader (Crazyflie Drop Down -> Bootloader) #Plotter Tab #Log Blocks Tab #Parameters Tab ==Swarm Client== The swarm Client is a re-creation of the Original Client but programmed in C and C++. ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] </center> c30dbe4f25e7fe2b2268cb310ae64c5990e28b86 80 79 2016-07-18T20:34:12Z Jnoronha 3 Added connect image wikitext text/x-wiki The PC Client software comes in many forms. The out-of-the-box Client is written in Python and has a Graphical User Interface (GUI). The GUI is well suited for beginners, but can only support a single Radio and a single Crazyflie at a time. The easiest way to start out is with the [https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze Virtual Machine (VM)], which comes with all the files and dependencies pre-installed and can run on any computer (Windows, Mac, Linux, etc.). For more advanced users who want to use the swarm capabilities of our platform will have to use the [[#Swarm Client|Swarm Client]] we developed in C and C++. ==[https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze VM]== ('''Note:''' The VM is updated frequently so the information below may be different than the current VM) The Bitcraze wiki has a tutorial on [https://wiki.bitcraze.io/projects:virtualmachine:tutorials:vmware-win7 installing the VM]. Along with another tutorial on how to get started [https://www.bitcraze.io/getting-started-with-development/ using the VM]. These are both very simple starting guides that will help you become familiar with the VM. ===Crazyflie Client GUI=== On the VM you can find the Crazyflie Client Graphical User Interface (GUI). To run the Client you want to open a terminal and navigate to <code>projects/''''FIND PATH''''</code> and then run the command <code>sudo ./bin/cfclient</code> (Alternatively, you can use the desktop to navigate to the folder and open a terminal there) Once you do that you should see something similar to this: [[Image:DefaultCrazyflieGUIMainScreen.JPG|500px]] This is the main screen of the Client GUI and there are many tabs and features that you can access directly from this screen. The most important parts of this screen are the following: #Connect Button #Bootloader (Crazyflie Drop Down -> Bootloader) #Plotter Tab #Log Blocks Tab #Parameters Tab ====Connect Button==== This is where you will scan for Crazyflies that are powered ON. All Crazyflies not already connected will show up in the popup [[Image:DefaultCrazyflieGUIConnectScreen.JPG|400px]] So we can see here that we got a return on Radio 0, from a Crazyflie on Channel 45 and a data rate of 2Mbps. ==Swarm Client== The swarm Client is a re-creation of the Original Client but programmed in C and C++. ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] </center> 955331e0e910528dd5669920254e1720f277d3b4 81 80 2016-07-19T02:48:09Z Jnoronha 3 Added Bootloader wikitext text/x-wiki The PC Client software comes in many forms. The out-of-the-box Client is written in Python and has a Graphical User Interface (GUI). The GUI is well suited for beginners, but can only support a single Radio and a single Crazyflie at a time. The easiest way to start out is with the [https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze Virtual Machine (VM)], which comes with all the files and dependencies pre-installed and can run on any computer (Windows, Mac, Linux, etc.). For more advanced users who want to use the swarm capabilities of our platform will have to use the [[#Swarm Client|Swarm Client]] we developed in C and C++. ==[https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze VM]== ('''Note:''' The VM is updated frequently so the information below may be different than the current VM) The Bitcraze wiki has a tutorial on [https://wiki.bitcraze.io/projects:virtualmachine:tutorials:vmware-win7 installing the VM]. Along with another tutorial on how to get started [https://www.bitcraze.io/getting-started-with-development/ using the VM]. These are both very simple starting guides that will help you become familiar with the VM. ===Crazyflie Client GUI=== On the VM you can find the Crazyflie Client Graphical User Interface (GUI). To run the Client you want to open a terminal and navigate to <code>projects/''''FIND PATH''''</code> and then run the command <code>sudo ./bin/cfclient</code> (Alternatively, you can use the desktop to navigate to the folder and open a terminal there) Once you do that you should see something similar to this: [[Image:DefaultCrazyflieGUIMainScreen.JPG|500px]] This is the main screen of the Client GUI and there are many tabs and features that you can access directly from this screen. The most important parts of this screen are the following: #Connect Button #Bootloader (Crazyflie Drop Down -> Bootloader) #Plotter Tab #Log Blocks Tab #Parameters Tab ====Connect Button==== This is where you will scan for Crazyflies that are powered ON. All Crazyflies not already connected will show up in the popup [[Image:DefaultCrazyflieGUIConnectScreen.JPG|400px]] We get a return that says <code>radio://0/45/2M</code>, this line is the identifier string of the Crazyflie we are trying to connect to. What this is saying is that we got a return from a Radio (Radio 0 specifically), from a Crazyflie on Channel 45 using a data rate of 2Mbps. ====Bootloader==== This where you can install new Firmware to the Crazyflie. [[Image:DefaultCrazyflieGUIBootloader.JPG|500px]] The first thing you'll need to update is to build the Firmware version you want into a .bin file. You can do this by just running the <code>make</code> command in terminal while located inside the Firmware directory you have modified. ==Swarm Client== The swarm Client is a re-creation of the Original Client but programmed in C and C++. ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] </center> a1a55e7bd9265d48c710eb3b5a50ca86c7b6e924 82 81 2016-07-19T03:14:24Z Jnoronha 3 Added how to flash firmware wikitext text/x-wiki The PC Client software comes in many forms. The out-of-the-box Client is written in Python and has a Graphical User Interface (GUI). The GUI is well suited for beginners, but can only support a single Radio and a single Crazyflie at a time. The easiest way to start out is with the [https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze Virtual Machine (VM)], which comes with all the files and dependencies pre-installed and can run on any computer (Windows, Mac, Linux, etc.). For more advanced users who want to use the swarm capabilities of our platform will have to use the [[#Swarm Client|Swarm Client]] we developed in C and C++. ==[https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze VM]== ('''Note:''' The VM is updated frequently so the information below may be different than the current VM) The Bitcraze wiki has a tutorial on [https://wiki.bitcraze.io/projects:virtualmachine:tutorials:vmware-win7 installing the VM]. Along with another tutorial on how to get started [https://www.bitcraze.io/getting-started-with-development/ using the VM]. These are both very simple starting guides that will help you become familiar with the VM. ===Crazyflie Client GUI=== On the VM you can find the Crazyflie Client Graphical User Interface (GUI). To run the Client you want to open a terminal and navigate to <code>projects/''''FIND PATH''''</code> and then run the command <code>sudo ./bin/cfclient</code> (Alternatively, you can use the desktop to navigate to the folder and open a terminal there) Once you do that you should see something similar to this: [[Image:DefaultCrazyflieGUIMainScreen.JPG|500px]] This is the main screen of the Client GUI and there are many tabs and features that you can access directly from this screen. The most important parts of this screen are the following: #Connect Button #Bootloader (Crazyflie Drop Down -> Bootloader) #Plotter Tab #Log Blocks Tab #Parameters Tab ====Connect Button==== This is where you will scan for Crazyflies that are powered ON. All Crazyflies not already connected will show up in the popup [[Image:DefaultCrazyflieGUIConnectScreen.JPG|400px]] We get a return that says <code>radio://0/45/2M</code>, this line is the identifier string of the Crazyflie we are trying to connect to. What this is saying is that we got a return from a Radio (Radio 0 specifically), from a Crazyflie on Channel 45 using a data rate of 2Mbps. ====Bootloader==== This where you can install new Firmware to the Crazyflie. [[Image:DefaultCrazyflieGUIBootloader.JPG|500px]] The first thing you'll need to update is to build the Firmware version you want into a .bin file. You can do this by just running the <code>make</code> command in terminal while located inside the Firmware directory you have modified. Once you have that .bin file built you: #Open the bootloader shown #Hold down the power button on the Crazyflie 2.0 for around 3 seconds until the 2 blue LED's flash and alternate. This puts the Crazyflie in bootloader mode. ('''NOTE:''' Recommend having '''ALL other Crazyflies OFF''' or else it could accidentally flash both Crazyflies.) #Then hit ''Initiate bootloader cold boot'' (it should connect to the Crazyflie in bootloader mode after a few seconds, Status will change from 'Not Connected' to 'Connected') #Hit ''Browse'' and find the .bin file you built earlier. #Then click ''Program'' and wait for the progress bar to complete. #Restart the Crazyflie in Firmware mode and make sure it starts up normally, if something seems wrong just repeat steps 2 through 6 again. ==Swarm Client== The swarm Client is a re-creation of the Original Client but programmed in C and C++. ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] </center> 80cb5997edf2f5d2c0a2f6f83b759f7753e77a44 83 82 2016-07-19T16:59:28Z Jnoronha 3 Finished Logging wikitext text/x-wiki The PC Client software comes in many forms. The out-of-the-box Client is written in Python and has a Graphical User Interface (GUI). The GUI is well suited for beginners, but can only support a single Radio and a single Crazyflie at a time. The easiest way to start out is with the [https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze Virtual Machine (VM)], which comes with all the files and dependencies pre-installed and can run on any computer (Windows, Mac, Linux, etc.). For more advanced users who want to use the swarm capabilities of our platform will have to use the [[#Swarm Client|Swarm Client]] we developed in C and C++. ==[https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze VM]== ('''Note:''' The VM is updated frequently so the information below may be different than the current VM) The Bitcraze wiki has a tutorial on [https://wiki.bitcraze.io/projects:virtualmachine:tutorials:vmware-win7 installing the VM]. Along with another tutorial on how to get started [https://www.bitcraze.io/getting-started-with-development/ using the VM]. These are both very simple starting guides that will help you become familiar with the VM. ===Crazyflie Client GUI=== On the VM you can find the Crazyflie Client Graphical User Interface (GUI). To run the Client you want to open a terminal and navigate to <code>projects/''''FIND PATH''''</code> and then run the command <code>sudo ./bin/cfclient</code> (Alternatively, you can use the desktop to navigate to the folder and open a terminal there) Once you do that you should see something similar to this: [[Image:DefaultCrazyflieGUIMainScreen.JPG|500px]] This is the main screen of the Client GUI and there are many tabs and features that you can access directly from this screen. The most important parts of this screen are the following: #Connect Button #Bootloader (Crazyflie Drop Down -> Bootloader) #Plotter Tab #Log Blocks Tab #Parameters Tab ====Connect Button==== This is where you will scan for Crazyflies that are powered ON. All Crazyflies not already connected will show up in the popup [[Image:DefaultCrazyflieGUIConnectScreen.JPG|400px]] We get a return that says <code>radio://0/45/2M</code>, this line is the identifier string of the Crazyflie we are trying to connect to. What this is saying is that we got a return from a Radio (Radio 0 specifically), from a Crazyflie on Channel 45 using a data rate of 2Mbps. ====Bootloader==== This where you can install new Firmware to the Crazyflie. [[Image:DefaultCrazyflieGUIBootloader.JPG|500px]] The first thing you'll need to update is to build the Firmware version you want into a .bin file. You can do this by just running the <code>make</code> command in terminal while located inside the Firmware directory you have modified. Once you have that .bin file built you: #Open the bootloader shown #Hold down the power button on the Crazyflie 2.0 for around 3 seconds until the 2 blue LED's flash and alternate. This puts the Crazyflie in bootloader mode. ('''NOTE:''' Recommend having '''ALL other Crazyflies OFF''' or else it could accidentally flash both Crazyflies.) #Then hit ''Initiate bootloader cold boot'' (it should connect to the Crazyflie in bootloader mode after a few seconds, Status will change from 'Not Connected' to 'Connected') #Hit ''Browse'' and find the .bin file you built earlier. #Then click ''Program'' and wait for the progress bar to complete. #Restart the Crazyflie in Firmware mode and make sure it starts up normally, if something seems wrong just repeat steps 2 through 6 again. ====Logging Tab==== Once you connect to a Crazyflie you can monitor certain log variables that have been set up. You will see a plot of the data similar to this: [[Image:DefaultCrazyflieGUILoggerScreen.JPG|400px]] On this screen we can do the following things: *Dropdown Menu at the top of the screen **Select which log block you want to plot on screen. *Scale the X-axis of the plot by: **Range **Number of Samples **Time in Seconds **Manually *Scale the Y-axis by: **Automatically **Manual Range ====Parameters Tab==== [[Image:DefaultCrazyflieGUIParametersScreen.JPG|400px]] ==Swarm Client== The swarm Client is a re-creation of the Original Client but programmed in C and C++. ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] </center> f0be0ba5da4f75c6222a9c7d3cf0690f28dbb3c5 84 83 2016-07-19T17:07:34Z Jnoronha 3 Finished Parameters Section wikitext text/x-wiki The PC Client software comes in many forms. The out-of-the-box Client is written in Python and has a Graphical User Interface (GUI). The GUI is well suited for beginners, but can only support a single Radio and a single Crazyflie at a time. The easiest way to start out is with the [https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze Virtual Machine (VM)], which comes with all the files and dependencies pre-installed and can run on any computer (Windows, Mac, Linux, etc.). For more advanced users who want to use the swarm capabilities of our platform will have to use the [[#Swarm Client|Swarm Client]] we developed in C and C++. ==[https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze VM]== ('''Note:''' The VM is updated frequently so the information below may be different than the current VM) The Bitcraze wiki has a tutorial on [https://wiki.bitcraze.io/projects:virtualmachine:tutorials:vmware-win7 installing the VM]. Along with another tutorial on how to get started [https://www.bitcraze.io/getting-started-with-development/ using the VM]. These are both very simple starting guides that will help you become familiar with the VM. ===Crazyflie Client GUI=== On the VM you can find the Crazyflie Client Graphical User Interface (GUI). To run the Client you want to open a terminal and navigate to <code>projects/''''FIND PATH''''</code> and then run the command <code>sudo ./bin/cfclient</code> (Alternatively, you can use the desktop to navigate to the folder and open a terminal there) Once you do that you should see something similar to this: [[Image:DefaultCrazyflieGUIMainScreen.JPG|500px]] This is the main screen of the Client GUI and there are many tabs and features that you can access directly from this screen. The most important parts of this screen are the following: #Connect Button #Bootloader (Crazyflie Drop Down -> Bootloader) #Plotter Tab #Log Blocks Tab #Parameters Tab ====Connect Button==== This is where you will scan for Crazyflies that are powered ON. All Crazyflies not already connected will show up in the popup [[Image:DefaultCrazyflieGUIConnectScreen.JPG|400px]] We get a return that says <code>radio://0/45/2M</code>, this line is the identifier string of the Crazyflie we are trying to connect to. What this is saying is that we got a return from a Radio (Radio 0 specifically), from a Crazyflie on Channel 45 using a data rate of 2Mbps. ====Bootloader==== This where you can install new Firmware to the Crazyflie. [[Image:DefaultCrazyflieGUIBootloader.JPG|500px]] The first thing you'll need to update is to build the Firmware version you want into a .bin file. You can do this by just running the <code>make</code> command in terminal while located inside the Firmware directory you have modified. Once you have that .bin file built you: #Open the bootloader shown #Hold down the power button on the Crazyflie 2.0 for around 3 seconds until the 2 blue LED's flash and alternate. This puts the Crazyflie in bootloader mode. ('''NOTE:''' Recommend having '''ALL other Crazyflies OFF''' or else it could accidentally flash both Crazyflies.) #Then hit ''Initiate bootloader cold boot'' (it should connect to the Crazyflie in bootloader mode after a few seconds, Status will change from 'Not Connected' to 'Connected') #Hit ''Browse'' and find the .bin file you built earlier. #Then click ''Program'' and wait for the progress bar to complete. #Restart the Crazyflie in Firmware mode and make sure it starts up normally, if something seems wrong just repeat steps 2 through 6 again. ====Logging Tab==== Once you connect to a Crazyflie you can monitor certain log variables that have been set up. You will see a plot of the data similar to this: [[Image:DefaultCrazyflieGUILoggerScreen.JPG|400px]] On this screen we can do the following things: *Dropdown Menu at the top of the screen **Select which log block you want to plot on screen. *Scale the X-axis of the plot by: **Range **Number of Samples **Time in Seconds **Manually *Scale the Y-axis by: **Automatically **Manual Range ====Parameters Tab==== This tab displays all the parameters currently set up on the Crazyflie Firmware. Once you connect to a Crazyflie it lists these parameters in a table format similar to below: [[Image:DefaultCrazyflieGUIParametersScreen.JPG|400px]] For each parameter we get its Name, Variable Type, Access Type (Read/Write), and its Current Value. We can also modify the parameter values on this screen in real-time and the changes will be sent to the Crazyflie automatically. ('''Note:''' Any parameter changes made on this screen are NOT preserved when you turn OFF the Crazyflie.) ==Swarm Client== The swarm Client is a re-creation of the Original Client but programmed in C and C++. ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] </center> 654954ef38cb901d64d270c260b129d74380ea5d 85 84 2016-07-19T17:41:40Z Jnoronha 3 /* Swarm Client */ Added up to step 3 in the Swarm Client wikitext text/x-wiki The PC Client software comes in many forms. The out-of-the-box Client is written in Python and has a Graphical User Interface (GUI). The GUI is well suited for beginners, but can only support a single Radio and a single Crazyflie at a time. The easiest way to start out is with the [https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze Virtual Machine (VM)], which comes with all the files and dependencies pre-installed and can run on any computer (Windows, Mac, Linux, etc.). For more advanced users who want to use the swarm capabilities of our platform will have to use the [[#Swarm Client|Swarm Client]] we developed in C and C++. ==[https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze VM]== ('''Note:''' The VM is updated frequently so the information below may be different than the current VM) The Bitcraze wiki has a tutorial on [https://wiki.bitcraze.io/projects:virtualmachine:tutorials:vmware-win7 installing the VM]. Along with another tutorial on how to get started [https://www.bitcraze.io/getting-started-with-development/ using the VM]. These are both very simple starting guides that will help you become familiar with the VM. ===Crazyflie Client GUI=== On the VM you can find the Crazyflie Client Graphical User Interface (GUI). To run the Client you want to open a terminal and navigate to <code>projects/''''FIND PATH''''</code> and then run the command <code>sudo ./bin/cfclient</code> (Alternatively, you can use the desktop to navigate to the folder and open a terminal there) Once you do that you should see something similar to this: [[Image:DefaultCrazyflieGUIMainScreen.JPG|500px]] This is the main screen of the Client GUI and there are many tabs and features that you can access directly from this screen. The most important parts of this screen are the following: #Connect Button #Bootloader (Crazyflie Drop Down -> Bootloader) #Plotter Tab #Log Blocks Tab #Parameters Tab ====Connect Button==== This is where you will scan for Crazyflies that are powered ON. All Crazyflies not already connected will show up in the popup [[Image:DefaultCrazyflieGUIConnectScreen.JPG|400px]] We get a return that says <code>radio://0/45/2M</code>, this line is the identifier string of the Crazyflie we are trying to connect to. What this is saying is that we got a return from a Radio (Radio 0 specifically), from a Crazyflie on Channel 45 using a data rate of 2Mbps. ====Bootloader==== This where you can install new Firmware to the Crazyflie. [[Image:DefaultCrazyflieGUIBootloader.JPG|500px]] The first thing you'll need to update is to build the Firmware version you want into a .bin file. You can do this by just running the <code>make</code> command in terminal while located inside the Firmware directory you have modified. Once you have that .bin file built you: #Open the bootloader shown #Hold down the power button on the Crazyflie 2.0 for around 3 seconds until the 2 blue LED's flash and alternate. This puts the Crazyflie in bootloader mode. ('''NOTE:''' Recommend having '''ALL other Crazyflies OFF''' or else it could accidentally flash both Crazyflies.) #Then hit ''Initiate bootloader cold boot'' (it should connect to the Crazyflie in bootloader mode after a few seconds, Status will change from 'Not Connected' to 'Connected') #Hit ''Browse'' and find the .bin file you built earlier. #Then click ''Program'' and wait for the progress bar to complete. #Restart the Crazyflie in Firmware mode and make sure it starts up normally, if something seems wrong just repeat steps 2 through 6 again. ====Logging Tab==== Once you connect to a Crazyflie you can monitor certain log variables that have been set up. You will see a plot of the data similar to this: [[Image:DefaultCrazyflieGUILoggerScreen.JPG|400px]] On this screen we can do the following things: *Dropdown Menu at the top of the screen **Select which log block you want to plot on screen. *Scale the X-axis of the plot by: **Range **Number of Samples **Time in Seconds **Manually *Scale the Y-axis by: **Automatically **Manual Range ====Parameters Tab==== This tab displays all the parameters currently set up on the Crazyflie Firmware. Once you connect to a Crazyflie it lists these parameters in a table format similar to below: [[Image:DefaultCrazyflieGUIParametersScreen.JPG|400px]] For each parameter we get its Name, Variable Type, Access Type (Read/Write), and its Current Value. We can also modify the parameter values on this screen in real-time and the changes will be sent to the Crazyflie automatically. ('''Note:''' Any parameter changes made on this screen are NOT preserved when you turn OFF the Crazyflie.) ==Swarm Client== The swarm Client is a re-creation of the Original Client but programmed in C and C++. The benefit of this is that *We use a unified language between Client and Firmware *Easily migrate this platform to any linux distribution that can install the Crazyflie dependencies. **Our platform code itself requires only the VRPN libraries and a generic C compiler. ===Using the Swarm Client=== The Swarm Client uses the terminal interface for User Input. :1. The first thing you want to do before any testing is to run the <code>sudo make</code> command in the Swarm Client directory. (Yes, the 'sudo' is necessary) ::This will make sure you have all the necessary dependencies, that the code is error free, and then it will build an executable (.exe) file of the Swarm Client code. An error free make will look something like this: :2. Before we run the .exe we need to run through a checklist ::*Camera System is Turned on and Crazyflie Trackables are opened and visible. ::*Radios are plugged into the USB Ports on the Client computer. ::*Crazyflies are ON and NOT in an Error State. :3. Run the executable file using the command <code>sudo ./eris_vrpn</code> in the same directory (Yes, the 'sudo' is necessary). This will start the program initialization and a bunch of status info will flood the screen. You will know the program is ready for input when you see the following: ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] </center> f2e108f3a27b1948b2c16080d04d303062591da7 94 85 2016-07-19T18:11:03Z Jnoronha 3 /* Swarm Client */ Added Keyboard Commands wikitext text/x-wiki The PC Client software comes in many forms. The out-of-the-box Client is written in Python and has a Graphical User Interface (GUI). The GUI is well suited for beginners, but can only support a single Radio and a single Crazyflie at a time. The easiest way to start out is with the [https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze Virtual Machine (VM)], which comes with all the files and dependencies pre-installed and can run on any computer (Windows, Mac, Linux, etc.). For more advanced users who want to use the swarm capabilities of our platform will have to use the [[#Swarm Client|Swarm Client]] we developed in C and C++. ==[https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze VM]== ('''Note:''' The VM is updated frequently so the information below may be different than the current VM) The Bitcraze wiki has a tutorial on [https://wiki.bitcraze.io/projects:virtualmachine:tutorials:vmware-win7 installing the VM]. Along with another tutorial on how to get started [https://www.bitcraze.io/getting-started-with-development/ using the VM]. These are both very simple starting guides that will help you become familiar with the VM. ===Crazyflie Client GUI=== On the VM you can find the Crazyflie Client Graphical User Interface (GUI). To run the Client you want to open a terminal and navigate to <code>projects/''''FIND PATH''''</code> and then run the command <code>sudo ./bin/cfclient</code> (Alternatively, you can use the desktop to navigate to the folder and open a terminal there) Once you do that you should see something similar to this: [[Image:DefaultCrazyflieGUIMainScreen.JPG|500px]] This is the main screen of the Client GUI and there are many tabs and features that you can access directly from this screen. The most important parts of this screen are the following: #Connect Button #Bootloader (Crazyflie Drop Down -> Bootloader) #Plotter Tab #Log Blocks Tab #Parameters Tab ====Connect Button==== This is where you will scan for Crazyflies that are powered ON. All Crazyflies not already connected will show up in the popup [[Image:DefaultCrazyflieGUIConnectScreen.JPG|400px]] We get a return that says <code>radio://0/45/2M</code>, this line is the identifier string of the Crazyflie we are trying to connect to. What this is saying is that we got a return from a Radio (Radio 0 specifically), from a Crazyflie on Channel 45 using a data rate of 2Mbps. ====Bootloader==== This where you can install new Firmware to the Crazyflie. [[Image:DefaultCrazyflieGUIBootloader.JPG|500px]] The first thing you'll need to update is to build the Firmware version you want into a .bin file. You can do this by just running the <code>make</code> command in terminal while located inside the Firmware directory you have modified. Once you have that .bin file built you: #Open the bootloader shown #Hold down the power button on the Crazyflie 2.0 for around 3 seconds until the 2 blue LED's flash and alternate. This puts the Crazyflie in bootloader mode. ('''NOTE:''' Recommend having '''ALL other Crazyflies OFF''' or else it could accidentally flash both Crazyflies.) #Then hit ''Initiate bootloader cold boot'' (it should connect to the Crazyflie in bootloader mode after a few seconds, Status will change from 'Not Connected' to 'Connected') #Hit ''Browse'' and find the .bin file you built earlier. #Then click ''Program'' and wait for the progress bar to complete. #Restart the Crazyflie in Firmware mode and make sure it starts up normally, if something seems wrong just repeat steps 2 through 6 again. ====Logging Tab==== Once you connect to a Crazyflie you can monitor certain log variables that have been set up. You will see a plot of the data similar to this: [[Image:DefaultCrazyflieGUILoggerScreen.JPG|400px]] On this screen we can do the following things: *Dropdown Menu at the top of the screen **Select which log block you want to plot on screen. *Scale the X-axis of the plot by: **Range **Number of Samples **Time in Seconds **Manually *Scale the Y-axis by: **Automatically **Manual Range ====Parameters Tab==== This tab displays all the parameters currently set up on the Crazyflie Firmware. Once you connect to a Crazyflie it lists these parameters in a table format similar to below: [[Image:DefaultCrazyflieGUIParametersScreen.JPG|400px]] For each parameter we get its Name, Variable Type, Access Type (Read/Write), and its Current Value. We can also modify the parameter values on this screen in real-time and the changes will be sent to the Crazyflie automatically. ('''Note:''' Any parameter changes made on this screen are NOT preserved when you turn OFF the Crazyflie.) ==Swarm Client== The swarm Client is a re-creation of the Original Client but programmed in C and C++. The benefit of this is that *We use a unified language between Client and Firmware *Easily migrate this platform to any linux distribution that can install the Crazyflie dependencies. **Our platform code itself requires only the VRPN libraries and a generic C compiler. ===Using the Swarm Client=== The Swarm Client uses the terminal interface for User Input. :1. The first thing you want to do before any testing is to run the <code>sudo make</code> command in the Swarm Client directory. (Yes, the 'sudo' is necessary) ::This will make sure you have all the necessary dependencies, that the code is error free, and then it will build an executable (.exe) file of the Swarm Client code. An error free make will look something like this: ::[[Image:CrazyflieTerminalPostMake.png|400px]] ::There will be warnings, but those don't cause any issues right now. :2. Pre-Test Checklist ::*Camera System is Turned on and Crazyflie Trackables are opened and visible. ::*Radios are plugged into the USB Ports on the Client computer. ::*Crazyflies are ON and NOT in an Error State. :3. Run the executable file using the command <code>sudo ./eris_vrpn</code> in the same directory (Yes, the 'sudo' is necessary). This will start the program initialization and a bunch of status info will flood the screen. You will know the program is ready for input when you see the following: ::[[Image:CrazyflieTerminalProgramStarted.png|400px]] ::This means that the Crazyflie yaw has been synchronized with the Camera system and they are ready to fly. :4. Input a Keyboard Command ::This will depend on what you have programmed as the keyboard input commands. As of 7/19/16 we have the following Keyboard Commands active: ::*'1' - Rotates Yaw of Crazyflie1 +45 degrees ::*'2' - Rotates Yaw of Crazyflie1 -45 degrees ::*'q' - Ends Main Loop (OBSOLETE - Replaced with ctrl + c) ::*'e' - Landing Mode (for ALL Crazyflies) ::*'t' - Crazyflie1 Take-Off ::*'y' - Crazyflie2 Take-Off ::*'u' - Crazyflie3 Take-Off ::*'i' - Crazyflie4 Take-Off ::*'h' - Hand Gesture Mode (for ALL Crazyflies) ::*'m' - Mirror Mode (for ALL Crazyflies) ::*ctrl+c - Quits Program, performs all cleanup. ::An example of what this would look like in the Terminal is shown here: ::[[Image:CrazyflieTerminalKeyboardInput.png|400px]] ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] </center> 35ea54767ef9b99757ee6f7b68ae21868d19320f 95 94 2016-07-19T18:31:31Z Jnoronha 3 /* Swarm Client */ Added Keyboard Input figure and finished 'Using the Platform Section' wikitext text/x-wiki The PC Client software comes in many forms. The out-of-the-box Client is written in Python and has a Graphical User Interface (GUI). The GUI is well suited for beginners, but can only support a single Radio and a single Crazyflie at a time. The easiest way to start out is with the [https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze Virtual Machine (VM)], which comes with all the files and dependencies pre-installed and can run on any computer (Windows, Mac, Linux, etc.). For more advanced users who want to use the swarm capabilities of our platform will have to use the [[#Swarm Client|Swarm Client]] we developed in C and C++. ==[https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze VM]== ('''Note:''' The VM is updated frequently so the information below may be different than the current VM) The Bitcraze wiki has a tutorial on [https://wiki.bitcraze.io/projects:virtualmachine:tutorials:vmware-win7 installing the VM]. Along with another tutorial on how to get started [https://www.bitcraze.io/getting-started-with-development/ using the VM]. These are both very simple starting guides that will help you become familiar with the VM. ===Crazyflie Client GUI=== On the VM you can find the Crazyflie Client Graphical User Interface (GUI). To run the Client you want to open a terminal and navigate to <code>projects/''''FIND PATH''''</code> and then run the command <code>sudo ./bin/cfclient</code> (Alternatively, you can use the desktop to navigate to the folder and open a terminal there) Once you do that you should see something similar to this: [[Image:DefaultCrazyflieGUIMainScreen.JPG|500px]] This is the main screen of the Client GUI and there are many tabs and features that you can access directly from this screen. The most important parts of this screen are the following: #Connect Button #Bootloader (Crazyflie Drop Down -> Bootloader) #Plotter Tab #Log Blocks Tab #Parameters Tab ====Connect Button==== This is where you will scan for Crazyflies that are powered ON. All Crazyflies not already connected will show up in the popup [[Image:DefaultCrazyflieGUIConnectScreen.JPG|400px]] We get a return that says <code>radio://0/45/2M</code>, this line is the identifier string of the Crazyflie we are trying to connect to. What this is saying is that we got a return from a Radio (Radio 0 specifically), from a Crazyflie on Channel 45 using a data rate of 2Mbps. ====Bootloader==== This where you can install new Firmware to the Crazyflie. [[Image:DefaultCrazyflieGUIBootloader.JPG|500px]] The first thing you'll need to update is to build the Firmware version you want into a .bin file. You can do this by just running the <code>make</code> command in terminal while located inside the Firmware directory you have modified. Once you have that .bin file built you: #Open the bootloader shown #Hold down the power button on the Crazyflie 2.0 for around 3 seconds until the 2 blue LED's flash and alternate. This puts the Crazyflie in bootloader mode. ('''NOTE:''' Recommend having '''ALL other Crazyflies OFF''' or else it could accidentally flash both Crazyflies.) #Then hit ''Initiate bootloader cold boot'' (it should connect to the Crazyflie in bootloader mode after a few seconds, Status will change from 'Not Connected' to 'Connected') #Hit ''Browse'' and find the .bin file you built earlier. #Then click ''Program'' and wait for the progress bar to complete. #Restart the Crazyflie in Firmware mode and make sure it starts up normally, if something seems wrong just repeat steps 2 through 6 again. ====Logging Tab==== Once you connect to a Crazyflie you can monitor certain log variables that have been set up. You will see a plot of the data similar to this: [[Image:DefaultCrazyflieGUILoggerScreen.JPG|400px]] On this screen we can do the following things: *Dropdown Menu at the top of the screen **Select which log block you want to plot on screen. *Scale the X-axis of the plot by: **Range **Number of Samples **Time in Seconds **Manually *Scale the Y-axis by: **Automatically **Manual Range ====Parameters Tab==== This tab displays all the parameters currently set up on the Crazyflie Firmware. Once you connect to a Crazyflie it lists these parameters in a table format similar to below: [[Image:DefaultCrazyflieGUIParametersScreen.JPG|400px]] For each parameter we get its Name, Variable Type, Access Type (Read/Write), and its Current Value. We can also modify the parameter values on this screen in real-time and the changes will be sent to the Crazyflie automatically. ('''Note:''' Any parameter changes made on this screen are NOT preserved when you turn OFF the Crazyflie.) ==Swarm Client== The swarm Client is a re-creation of the Original Client but programmed in C and C++. The benefit of this is that *We use a unified language between Client and Firmware *Easily migrate this platform to any linux distribution that can install the Crazyflie dependencies. **Our platform code itself requires only the VRPN libraries and a generic C compiler. ===Using the Swarm Client=== The Swarm Client uses the terminal interface for User Input. :1. The first thing you want to do before any testing is to run the <code>sudo make</code> command in the Swarm Client directory. (Yes, the 'sudo' is necessary) ::This will make sure you have all the necessary dependencies, that the code is error free, and then it will build an executable (.exe) file of the Swarm Client code. An error free make will look something like this: ::[[Image:CrazyflieTerminalPostMake.png|400px]] ::There will be warnings, but those don't cause any issues right now. :2. Pre-Test Checklist ::*Camera System is Turned on and Crazyflie Trackables are opened and visible. ::*Radios are plugged into the USB Ports on the Client computer. ::*Crazyflies are ON and NOT in an Error State. :3. Run the executable file using the command <code>sudo ./eris_vrpn</code> in the same directory (Yes, the 'sudo' is necessary). This will start the program initialization and a bunch of status info will flood the screen. You will know the program is ready for input when you see the following: ::[[Image:CrazyflieTerminalProgramStarted.png|400px]] ::This means that the Crazyflie yaw has been synchronized with the Camera system and they are ready to fly. :4. Input a Keyboard Command ::This will depend on what you have programmed as the keyboard input commands. As of 7/19/16 we have the following Keyboard Commands active: ::*'1' - Rotates Yaw of Crazyflie1 +45 degrees ::*'2' - Rotates Yaw of Crazyflie1 -45 degrees ::*'q' - Ends Main Loop (OBSOLETE - Replaced with ctrl + c) ::*'e' - Landing Mode (for ALL Crazyflies) ::*'t' - Crazyflie1 Take-Off ::*'y' - Crazyflie2 Take-Off ::*'u' - Crazyflie3 Take-Off ::*'i' - Crazyflie4 Take-Off ::*'h' - Hand Gesture Mode (for ALL Crazyflies) ::*'m' - Mirror Mode (for ALL Crazyflies) ::*ctrl+c - Quits Program, performs all cleanup. ::An example of what this would look like in the Terminal is shown here: ::[[Image:CrazyflieTerminalKeyboardInput.png|400px]] ::So you can see we commanded all 4 Crazyflies to take off (t,y,u,i), then activated Landing Mode (e), then activated Hand Mode (h), and then Ended the Program (ctrl+c). :5. End Program when finished (ctrl+c) ::This will end the program loop, print the current battery levels, and Delete the Radio pointers (shown at the end of the previous figure) ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] </center> 03e4d1e683f4e220188bc33aa996d02a4a7e1343 96 95 2016-07-19T18:41:28Z Jnoronha 3 /* Swarm Client */ Added Initial state Terminal figure wikitext text/x-wiki The PC Client software comes in many forms. The out-of-the-box Client is written in Python and has a Graphical User Interface (GUI). The GUI is well suited for beginners, but can only support a single Radio and a single Crazyflie at a time. The easiest way to start out is with the [https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze Virtual Machine (VM)], which comes with all the files and dependencies pre-installed and can run on any computer (Windows, Mac, Linux, etc.). For more advanced users who want to use the swarm capabilities of our platform will have to use the [[#Swarm Client|Swarm Client]] we developed in C and C++. ==[https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze VM]== ('''Note:''' The VM is updated frequently so the information below may be different than the current VM) The Bitcraze wiki has a tutorial on [https://wiki.bitcraze.io/projects:virtualmachine:tutorials:vmware-win7 installing the VM]. Along with another tutorial on how to get started [https://www.bitcraze.io/getting-started-with-development/ using the VM]. These are both very simple starting guides that will help you become familiar with the VM. ===Crazyflie Client GUI=== On the VM you can find the Crazyflie Client Graphical User Interface (GUI). To run the Client you want to open a terminal and navigate to <code>projects/''''FIND PATH''''</code> and then run the command <code>sudo ./bin/cfclient</code> (Alternatively, you can use the desktop to navigate to the folder and open a terminal there) Once you do that you should see something similar to this: [[Image:DefaultCrazyflieGUIMainScreen.JPG|500px]] This is the main screen of the Client GUI and there are many tabs and features that you can access directly from this screen. The most important parts of this screen are the following: #Connect Button #Bootloader (Crazyflie Drop Down -> Bootloader) #Plotter Tab #Log Blocks Tab #Parameters Tab ====Connect Button==== This is where you will scan for Crazyflies that are powered ON. All Crazyflies not already connected will show up in the popup [[Image:DefaultCrazyflieGUIConnectScreen.JPG|400px]] We get a return that says <code>radio://0/45/2M</code>, this line is the identifier string of the Crazyflie we are trying to connect to. What this is saying is that we got a return from a Radio (Radio 0 specifically), from a Crazyflie on Channel 45 using a data rate of 2Mbps. ====Bootloader==== This where you can install new Firmware to the Crazyflie. [[Image:DefaultCrazyflieGUIBootloader.JPG|500px]] The first thing you'll need to update is to build the Firmware version you want into a .bin file. You can do this by just running the <code>make</code> command in terminal while located inside the Firmware directory you have modified. Once you have that .bin file built you: #Open the bootloader shown #Hold down the power button on the Crazyflie 2.0 for around 3 seconds until the 2 blue LED's flash and alternate. This puts the Crazyflie in bootloader mode. ('''NOTE:''' Recommend having '''ALL other Crazyflies OFF''' or else it could accidentally flash both Crazyflies.) #Then hit ''Initiate bootloader cold boot'' (it should connect to the Crazyflie in bootloader mode after a few seconds, Status will change from 'Not Connected' to 'Connected') #Hit ''Browse'' and find the .bin file you built earlier. #Then click ''Program'' and wait for the progress bar to complete. #Restart the Crazyflie in Firmware mode and make sure it starts up normally, if something seems wrong just repeat steps 2 through 6 again. ====Logging Tab==== Once you connect to a Crazyflie you can monitor certain log variables that have been set up. You will see a plot of the data similar to this: [[Image:DefaultCrazyflieGUILoggerScreen.JPG|400px]] On this screen we can do the following things: *Dropdown Menu at the top of the screen **Select which log block you want to plot on screen. *Scale the X-axis of the plot by: **Range **Number of Samples **Time in Seconds **Manually *Scale the Y-axis by: **Automatically **Manual Range ====Parameters Tab==== This tab displays all the parameters currently set up on the Crazyflie Firmware. Once you connect to a Crazyflie it lists these parameters in a table format similar to below: [[Image:DefaultCrazyflieGUIParametersScreen.JPG|400px]] For each parameter we get its Name, Variable Type, Access Type (Read/Write), and its Current Value. We can also modify the parameter values on this screen in real-time and the changes will be sent to the Crazyflie automatically. ('''Note:''' Any parameter changes made on this screen are NOT preserved when you turn OFF the Crazyflie.) ==Swarm Client== The swarm Client is a re-creation of the Original Client but programmed in C and C++. The benefit of this is that *We use a unified language between Client and Firmware *Easily migrate this platform to any linux distribution that can install the Crazyflie dependencies. **Our platform code itself requires only the VRPN libraries and a generic C compiler. ===Using the Swarm Client=== The Swarm Client uses the terminal interface for User Input. [[Image:CrazyflieTerminalInitial.png|400px]] Here we see what the initial Terminal looks like before we do anything. :1. The first thing you want to do before any testing is to run the <code>sudo make</code> command in the Swarm Client directory. (Yes, the 'sudo' is necessary) ::This will make sure you have all the necessary dependencies, that the code is error free, and then it will build an executable (.exe) file of the Swarm Client code. An error free make will look something like this: ::[[Image:CrazyflieTerminalPostMake.png|400px]] ::There will be warnings, but those don't cause any issues right now. :2. Pre-Test Checklist ::*Camera System is Turned on and Crazyflie Trackables are opened and visible. ::*Radios are plugged into the USB Ports on the Client computer. ::*Crazyflies are ON and NOT in an Error State. :3. Run the executable file using the command <code>sudo ./eris_vrpn</code> in the same directory (Yes, the 'sudo' is necessary). This will start the program initialization and a bunch of status info will flood the screen. You will know the program is ready for input when you see the following: ::[[Image:CrazyflieTerminalProgramStarted.png|400px]] ::This means that the Crazyflie yaw has been synchronized with the Camera system and they are ready to fly. :4. Input a Keyboard Command ::This will depend on what you have programmed as the keyboard input commands. As of 7/19/16 we have the following Keyboard Commands active: ::*'1' - Rotates Yaw of Crazyflie1 +45 degrees ::*'2' - Rotates Yaw of Crazyflie1 -45 degrees ::*'q' - Ends Main Loop (OBSOLETE - Replaced with ctrl + c) ::*'e' - Landing Mode (for ALL Crazyflies) ::*'t' - Crazyflie1 Take-Off ::*'y' - Crazyflie2 Take-Off ::*'u' - Crazyflie3 Take-Off ::*'i' - Crazyflie4 Take-Off ::*'h' - Hand Gesture Mode (for ALL Crazyflies) ::*'m' - Mirror Mode (for ALL Crazyflies) ::*ctrl+c - Quits Program, performs all cleanup. ::An example of what this would look like in the Terminal is shown here: ::[[Image:CrazyflieTerminalKeyboardInput.png|400px]] ::So you can see we commanded all 4 Crazyflies to take off (t,y,u,i), then activated Landing Mode (e), then activated Hand Mode (h), and then Ended the Program (ctrl+c). :5. End Program when finished (ctrl+c) ::This will end the program loop, print the current battery levels, and Delete the Radio pointers (shown at the end of the previous figure) ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] </center> 926454589f42bf17b88608afa4c643071a3275a7 Firmware 0 26 58 2016-07-12T18:09:04Z Jnoronha 3 Added Navigation bar wikitext text/x-wiki ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] </center> 6a8ddcb3ad33d00f0c67854f6f60de327dbe70cb Controller 0 5 60 20 2016-07-12T20:50:26Z Jnoronha 3 Added overview of original Firmware PID's wikitext text/x-wiki The Crazyflie platform is completely customizable when it comes to the control design. As long as the controller can be written in C or C++, we can implement it in the Platform. This applies to both the controllers run on the PC Client and the controllers run on the Firmware of the Crazyflie. Originally the only controllers in the Platform were Firmware PID's that controlled the angular position and rates of the Crazyflie for hand flight. The original controller layout can be seen in '''Figure 1'''. Below you will find documentation on the different types of Controllers that have been applied to the platform, organized by their location in the Platform. == PC Client == === PID Controllers (Position and Yaw) === The first controller implemented on the Client was a PID controller used to stabilize the Crazyflie's position in X, Y, and Z. == Firmware == === Original PID Controllers (Angular Rotation) === On the Crazyflie Firmware there are 5 PID controllers as seen here: [[Image:FirmwareOnlyPIDArchitecture.png|500px]] The Pitch and Roll angular position PID's receive constant setpoints from some outside source (gamepad controller or automated controller). The outputs of those angular position controllers is then fed into the angular rate controllers as shown. This final output is then fed into the Motor Command block which converts the angular rate setpoints into motor commands. 5819aea3997ca1dbd2284b2895304061ccd531eb 61 60 2016-07-13T16:32:14Z Jnoronha 3 Added full PID client figure wikitext text/x-wiki The Crazyflie platform is completely customizable when it comes to the control design. As long as the controller can be written in C or C++, we can implement it in the Platform. This applies to both the controllers run on the PC Client and the controllers run on the Firmware of the Crazyflie. Originally the only controllers in the Platform were Firmware PID's that controlled the angular position and rates of the Crazyflie for hand flight. The original controller layout can be seen in '''Figure 1'''. Below you will find documentation on the different types of Controllers that have been applied to the platform, organized by their location in the Platform. == Firmware == === Original PID Controllers (Angular Rotation) === Directly on the Crazyflie Firmware there are 5 PID controllers as seen here: [[Image:FirmwareOnlyPIDArchitecture.png|500px]] The Pitch and Roll angular position PID's receive constant setpoints from some outside source (gamepad controller or automated controller). The outputs of those angular position controllers is then fed into the angular rate controllers as shown. This final output is then fed into the Motor Command block which converts the angular rate setpoints into motor commands. ---- ===State Estimator=== ('''***NOT YET IMPLEMENTED***''') Bitcraze is currently working on adding a state estimator onto the Firmware to handle control calculations instead of the PID. The code is in place but the controller is not yet used as of '''7/13/16'''. == PC Client == === PID Controllers (Position and Yaw) === The first controller implemented on the Client were 4 PID controllers used to stabilize the Crazyflie's position in X, Y, and Z, as well as angular position in Yaw respectively. These PID's feed directly into the Firmware PID's as seen here: [[Image:CompletePIDArchitectureFigure.png|500px]] The controllers inside the red box are the original PID controllers located on the [Controller:Firmware|Original PID Controllers (Angular Rotation) Firmware] 9712be7d0cb7f7b8d740bc52c4c3e1a242705794 62 61 2016-07-13T16:37:36Z Jnoronha 3 added link to original pid header in client PID section wikitext text/x-wiki The Crazyflie platform is completely customizable when it comes to the control design. As long as the controller can be written in C or C++, we can implement it in the Platform. This applies to both the controllers run on the PC Client and the controllers run on the Firmware of the Crazyflie. Originally the only controllers in the Platform were Firmware PID's that controlled the angular position and rates of the Crazyflie for hand flight. The original controller layout can be seen in '''Figure 1'''. Below you will find documentation on the different types of Controllers that have been applied to the platform, organized by their location in the Platform. == Firmware == === Original PID Controllers (Angular Rotation) === Directly on the Crazyflie Firmware there are 5 PID controllers as seen here: [[Image:FirmwareOnlyPIDArchitecture.png|500px]] The Pitch and Roll angular position PID's receive constant setpoints from some outside source (gamepad controller or automated controller). The outputs of those angular position controllers is then fed into the angular rate controllers as shown. This final output is then fed into the Motor Command block which converts the angular rate setpoints into motor commands. ---- ===State Estimator=== ('''***NOT YET IMPLEMENTED***''') Bitcraze is currently working on adding a state estimator onto the Firmware to handle control calculations instead of the PID. The code is in place but the controller is not yet used as of '''7/13/16'''. == PC Client == === PID Controllers (Position and Yaw) === The first controller implemented on the Client were 4 PID controllers used to stabilize the Crazyflie's position in X, Y, and Z, as well as angular position in Yaw respectively. These PID's feed directly into the Firmware PID's as seen here: [[Image:CompletePIDArchitectureFigure.png|500px]] The controllers inside the red box are the original PID controllers located on the Firmware as shown in the [[#Original PID Controllers (Angular Rotation)|Original PID's]]. b10e0ed950c5f80686f4c413ecae0ca5544648f4 63 62 2016-07-13T17:04:01Z Jnoronha 3 Added many steps to PID controller init wikitext text/x-wiki The Crazyflie platform is completely customizable when it comes to the control design. As long as the controller can be written in C or C++, we can implement it in the Platform. This applies to both the controllers run on the PC Client and the controllers run on the Firmware of the Crazyflie. Originally the only controllers in the Platform were Firmware PID's that controlled the angular position and rates of the Crazyflie for hand flight. The original controller layout can be seen in '''Figure 1'''. Below you will find documentation on the different types of Controllers that have been applied to the platform, organized by their location in the Platform. == Firmware == === Original PID Controllers (Angular Rotation) === Directly on the Crazyflie Firmware there are 5 PID controllers as seen here: [[Image:FirmwareOnlyPIDArchitecture.png|500px]] The Pitch and Roll angular position PID's receive constant setpoints from some outside source (gamepad controller or automated controller). The outputs of those angular position controllers is then fed into the angular rate controllers as shown. This final output is then fed into the Motor Command block which converts the angular rate setpoints into motor commands. ---- ===State Estimator=== ('''***NOT YET IMPLEMENTED***''') Bitcraze is currently working on adding a state estimator onto the Firmware to handle control calculations instead of the PID. The code is in place but the controller is not yet used as of '''7/13/16'''. == PC Client == === PID Controllers (Position and Yaw) === The first controller implemented on the Client were 4 PID controllers used to stabilize the Crazyflie's position in X, Y, and Z, as well as angular position in Yaw respectively. These PID's feed directly into the Firmware PID's as seen here: [[Image:CompletePIDArchitectureFigure.png|500px]] The controllers inside the red box are the original PID controllers located on the Firmware as shown above in the [[#Original PID Controllers (Angular Rotation)|Original PID's]]. ====Setting up the PID's==== :1. To start we create a struct with all the necessary variables (code from ''pid.h''): <blockquote> <code> <pre> typedef struct { float desired; //< set point float error; //< error float prevError; //< previous error float integ; //< integral float deriv; //< derivative float kp; //< proportional gain float ki; //< integral gain float kd; //< derivative gain float outP; //< proportional output (debugging) float outI; //< integral output (debugging) float outD; //< derivative output (debugging) float iLimit; //< integral limit float iLimitLow; //< integral limit float dt; //< delta-time dt float angularLimit; //sets limit for how far Crazyflie can tip, to prevent flipping float angularLimitLow; //^ float thrustLimit; //Sets upper limit for Thrust Output (60000?) **? float thrustLimitLow; //Sets lower limit for thrust Output (10001) } PidObject; </pre> </code> </blockquote> :2. To simplify scaling up the code to multiple Crazyflies, we will create a <code> ControllerObject </code> that contains multiple PID structs as shown (code in ''controller.h''): <blockquote> <code> <pre> typedef struct { PidObject pidRoll; PidObject pidPitch; PidObject pidYaw; PidObject pidX; PidObject pidY; PidObject pidZ; bool isInit; } ControllerObject; </pre> </code> </blockquote> :3. Then we initialize the Objects to 0 at the start of each run (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> ControllerObject pidCtrl1 = { 0 }; // init all fields to zero ControllerObject pidCtrl2 = { 0 }; // init all fields to zero ControllerObject pidCtrl3 = { 0 }; // init all fields to zero ControllerObject pidCtrl4 = { 0 }; // init all fields to zero </pre> </code> </blockquote> :4. Then populate the PidObjects with the desired parameters (code in ''pid.c''): <blockquote> <code> <pre> void pidInit(PidObject* pid, const float desired, const float kp, const float ki, const float kd, const float dt) { pid->error = 0; pid->prevError = 0; pid->integ = 0; pid->deriv = 0; pid->desired = desired; pid->kp = kp; pid->ki = ki; pid->kd = kd; pid->iLimit = DEFAULT_PID_INTEGRATION_LIMIT; pid->iLimitLow = -DEFAULT_PID_INTEGRATION_LIMIT; pid->angularLimit = DEFAULT_PID_ANGLE_OUTPUT; pid->angularLimitLow = -DEFAULT_PID_ANGLE_OUTPUT; pid->thrustLimit = DEFAULT_PID_HIGH_THRUST_LIMIT; pid->thrustLimitLow = DEFAULT_PID_LOW_THRUST_LIMIT; pid->dt = dt; } </pre> </code> </blockquote> Using the above function for each of the <code> PidObjects </code> inside of the <code> ControllerObject </code> below (code in ''controller.c''): <blockquote> <code> <pre> void controllerInit( ControllerObject * ctrl ) { if(ctrl->isInit) return; pidInit(&ctrl->pidY, 0, PID_Y_KP, PID_Y_KI, PID_Y_KD, CAMERA_UPDATE_DT); //for Roll PID pidInit(&ctrl->pidX, 0, PID_X_KP, PID_X_KI, PID_X_KD, CAMERA_UPDATE_DT); //for Pitch PID pidInit(&ctrl->pidYaw, 0, PID_YAW_KP, PID_YAW_KI, PID_YAW_KD, CAMERA_UPDATE_DT); pidInit(&ctrl->pidZ, 0, PID_Z_KP, PID_Z_KI, PID_Z_KD, CAMERA_UPDATE_DT); pidSetIntegralLimit(&ctrl->pidY, PID_Y_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidX, PID_X_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidYaw, PID_YAW_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidZ, PID_Z_INTEGRATION_LIMIT); ctrl->isInit = true; } </pre> </code> </blockquote> '''Note:'''If we have multiple Crazyflies we need a <code> ControllerObject </code> for each Crazyflie (code in ''eris_vrpn.cpp'') <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl1 ); controllerInit( &pidCtrl1 ); #endif #if NUM_QUADS >= 2 controllerResetAllPID( &pidCtrl2 ); controllerInit( &pidCtrl2 ); #endif #if NUM_QUADS >=3 controllerResetAllPID( &pidCtrl3 ); controllerInit( &pidCtrl3 ); #endif #if NUM_QUADS >=4 controllerResetAllPID( &pidCtrl4 ); controllerInit( &pidCtrl4 ); #endif </pre> </code> </blockquote> b3e45b4e9ad815e713c5480bee615b436048a27a 64 63 2016-07-13T17:43:55Z Jnoronha 3 Finished PID calculation how-to wikitext text/x-wiki The Crazyflie platform is completely customizable when it comes to the control design. As long as the controller can be written in C or C++, we can implement it in the Platform. This applies to both the controllers run on the PC Client and the controllers run on the Firmware of the Crazyflie. Originally the only controllers in the Platform were Firmware PID's that controlled the angular position and rates of the Crazyflie for hand flight. The original controller layout can be seen in '''Figure 1'''. Below you will find documentation on the different types of Controllers that have been applied to the platform, organized by their location in the Platform. == Firmware == === Original PID Controllers (Angular Rotation) === Directly on the Crazyflie Firmware there are 5 PID controllers as seen here: [[Image:FirmwareOnlyPIDArchitecture.png|500px]] The Pitch and Roll angular position PID's receive constant setpoints from some outside source (gamepad controller or automated controller). The outputs of those angular position controllers is then fed into the angular rate controllers as shown. This final output is then fed into the Motor Command block which converts the angular rate setpoints into motor commands. ---- ===State Estimator=== ('''***NOT YET IMPLEMENTED***''') Bitcraze is currently working on adding a state estimator onto the Firmware to handle control calculations instead of the PID. The code is in place but the controller is not yet used as of '''7/13/16'''. == PC Client == === PID Controllers (Position and Yaw) === The first controller implemented on the Client were 4 PID controllers used to stabilize the Crazyflie's position in X, Y, and Z, as well as angular position in Yaw respectively. These PID's feed directly into the Firmware PID's as seen here: [[Image:CompletePIDArchitectureFigure.png|500px]] The controllers inside the red box are the original PID controllers located on the Firmware as shown above in the [[#Original PID Controllers (Angular Rotation)|Original PID's]]. ====Initialize the PID's==== :1. To start we create a struct with all the necessary variables (code from ''pid.h''): <blockquote> <code> <pre> typedef struct { float desired; //< set point float error; //< error float prevError; //< previous error float integ; //< integral float deriv; //< derivative float kp; //< proportional gain float ki; //< integral gain float kd; //< derivative gain float outP; //< proportional output (debugging) float outI; //< integral output (debugging) float outD; //< derivative output (debugging) float iLimit; //< integral limit float iLimitLow; //< integral limit float dt; //< delta-time dt float angularLimit; //sets limit for how far Crazyflie can tip, to prevent flipping float angularLimitLow; //^ float thrustLimit; //Sets upper limit for Thrust Output (60000?) **? float thrustLimitLow; //Sets lower limit for thrust Output (10001) } PidObject; </pre> </code> </blockquote> :2. To simplify scaling up the code to multiple Crazyflies, we will create a <code> ControllerObject </code> that contains multiple PID structs as shown (code in ''controller.h''): <blockquote> <code> <pre> typedef struct { PidObject pidRoll; PidObject pidPitch; PidObject pidYaw; PidObject pidX; PidObject pidY; PidObject pidZ; bool isInit; } ControllerObject; </pre> </code> </blockquote> :3. Then we initialize the Objects to 0 at the start of each run (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> ControllerObject pidCtrl1 = { 0 }; // init all fields to zero ControllerObject pidCtrl2 = { 0 }; // init all fields to zero ControllerObject pidCtrl3 = { 0 }; // init all fields to zero ControllerObject pidCtrl4 = { 0 }; // init all fields to zero </pre> </code> </blockquote> :4. Then populate the PidObjects with the desired parameters (code in ''pid.c''): <blockquote> <code> <pre> void pidInit(PidObject* pid, const float desired, const float kp, const float ki, const float kd, const float dt) { pid->error = 0; pid->prevError = 0; pid->integ = 0; pid->deriv = 0; pid->desired = desired; pid->kp = kp; pid->ki = ki; pid->kd = kd; pid->iLimit = DEFAULT_PID_INTEGRATION_LIMIT; pid->iLimitLow = -DEFAULT_PID_INTEGRATION_LIMIT; pid->angularLimit = DEFAULT_PID_ANGLE_OUTPUT; pid->angularLimitLow = -DEFAULT_PID_ANGLE_OUTPUT; pid->thrustLimit = DEFAULT_PID_HIGH_THRUST_LIMIT; pid->thrustLimitLow = DEFAULT_PID_LOW_THRUST_LIMIT; pid->dt = dt; } </pre> </code> </blockquote> Using the above function for each of the <code> PidObjects </code> inside of the <code> ControllerObject </code> below (code in ''controller.c''): <blockquote> <code> <pre> void controllerInit( ControllerObject * ctrl ) { if(ctrl->isInit) return; pidInit(&ctrl->pidY, 0, PID_Y_KP, PID_Y_KI, PID_Y_KD, CAMERA_UPDATE_DT); //for Roll PID pidInit(&ctrl->pidX, 0, PID_X_KP, PID_X_KI, PID_X_KD, CAMERA_UPDATE_DT); //for Pitch PID pidInit(&ctrl->pidYaw, 0, PID_YAW_KP, PID_YAW_KI, PID_YAW_KD, CAMERA_UPDATE_DT); pidInit(&ctrl->pidZ, 0, PID_Z_KP, PID_Z_KI, PID_Z_KD, CAMERA_UPDATE_DT); pidSetIntegralLimit(&ctrl->pidY, PID_Y_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidX, PID_X_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidYaw, PID_YAW_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidZ, PID_Z_INTEGRATION_LIMIT); ctrl->isInit = true; } </pre> </code> </blockquote> '''Note:'''If we have multiple Crazyflies we need a <code> ControllerObject </code> for each Crazyflie (code in ''eris_vrpn.cpp'') <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl1 ); controllerInit( &pidCtrl1 ); #endif #if NUM_QUADS >= 2 controllerResetAllPID( &pidCtrl2 ); controllerInit( &pidCtrl2 ); #endif #if NUM_QUADS >=3 controllerResetAllPID( &pidCtrl3 ); controllerInit( &pidCtrl3 ); #endif #if NUM_QUADS >=4 controllerResetAllPID( &pidCtrl4 ); controllerInit( &pidCtrl4 ); #endif </pre> </code> </blockquote> Now the initialization of the Controllers is complete. ====Calculating the PID's==== :1. Each loop we want to calculate the PID output (code in ''pid.c''): <blockquote> <code> <pre> float pidUpdateAngle(PidObject* pid, const float measured, const bool updateError) //**USED FOR ATTITUDE CONTROL { float output; if(updateError) { pid->error = pid->desired - measured; //Calculates current error } pid->integ += pid->error * pid->dt; //Calculates integral term if(pid->integ > pid->iLimit) //Checks that the integral term stays below the integral limit (anti-windup) { pid->integ = pid->iLimit; } else if(pid->integ < pid->iLimitLow) { pid->integ = pid->iLimitLow; } pid->deriv = (pid->error - pid->prevError) / pid->dt; //Calculates derivative term pid->outP = pid->kp* pid->error; pid->outI = pid->ki * pid->integ; pid->outD = pid->kd * pid->deriv; output = pid->outP + pid->outI + pid->outD; //Adds up all 3 calculated terms for output if(output > pid->angularLimit) //Limits amount Crazyflie can tip { output = pid->angularLimit; } if(output < pid->angularLimitLow) //Limits amount Crazyflie can tip { output = pid->angularLimitLow; } pid->prevError = pid->error; //Stores the current error for next loop return output; } </pre> </code> </blockquote> '''Note:'''There are 3 different versions of this Function (for Angle, Thrust, and Yaw) since each has different output limits. :2. Using the function above, combine all PID calculations into one function (code in ''controller.c''): <blockquote> <code> <pre> void controllerCorrectAttitudePID(ControllerObject * ctrl, float xPositionActual, float yPositionActual, float zPositionActual, float eulerYawActual, float xPositionDesired, float yPositionDesired, float zPositionDesired, float eulerYawDesired, float* rollControlOutput, float* pitchControlOutput, float* yawControlOutput, float* thrustControlOutput) { pidSetDesired(&ctrl->pidX, xPositionDesired); *pitchControlOutput = pidUpdateAngle(&ctrl->pidX, xPositionActual, false); //Originally true pidSetDesired(&ctrl->pidY, yPositionDesired); *rollControlOutput = pidUpdateAngle(&ctrl->pidY, yPositionActual, false); //Originally true pidSetDesired(&ctrl->pidZ, zPositionDesired); *thrustControlOutput = pidUpdateThrust(&ctrl->pidZ,zPositionActual, true); float yawError; pidSetDesired(&ctrl->pidYaw, eulerYawDesired); yawError = eulerYawDesired - eulerYawActual; if(yawError > 180.0) //Ensures Yaw error stays between -180 and 180 degrees yawError -= 360.0; else if(yawError < -180.0) yawError += 360.0; pidSetError(&ctrl->pidYaw, yawError); *yawControlOutput = pidUpdateYaw(&ctrl->pidYaw, eulerYawActual, true); //originally false } </pre> </code> </blockquote> :3. In each Callback, calculate the Controller outputs, assigned to pointer values<code>*rollControlOutput</code>, <code>*pitchControlOutput</code>, etc... (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; //Calculates error externally controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); </pre> </code> </blockquote> '''Note:''' We calculate error externally for X and Y because certain swarm controllers need special setpoint modifiers (this way we can switch modes without effecting the default setpoint): '''Example:''' Follow Hand Mode Error (Crazyflie1 will have setpoint -0.5 m lower in X and +0.5 m higher in Y than your hand trackable): <blockquote> <code> <pre> ... xError1 = (xPositionHand - 0.5) - xPosition1; yError1 = (yPositionHand + 0.5) - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); ... </pre> </code> </blockquote> :4. Repeat for each set of new location data. 2b08acf4f7d47367e1ddb164fb3ec1aa50257cb4 65 64 2016-07-13T17:45:54Z Jnoronha 3 Fixed formatting on the notes wikitext text/x-wiki The Crazyflie platform is completely customizable when it comes to the control design. As long as the controller can be written in C or C++, we can implement it in the Platform. This applies to both the controllers run on the PC Client and the controllers run on the Firmware of the Crazyflie. Originally the only controllers in the Platform were Firmware PID's that controlled the angular position and rates of the Crazyflie for hand flight. The original controller layout can be seen in '''Figure 1'''. Below you will find documentation on the different types of Controllers that have been applied to the platform, organized by their location in the Platform. == Firmware == === Original PID Controllers (Angular Rotation) === Directly on the Crazyflie Firmware there are 5 PID controllers as seen here: [[Image:FirmwareOnlyPIDArchitecture.png|500px]] The Pitch and Roll angular position PID's receive constant setpoints from some outside source (gamepad controller or automated controller). The outputs of those angular position controllers is then fed into the angular rate controllers as shown. This final output is then fed into the Motor Command block which converts the angular rate setpoints into motor commands. ---- ===State Estimator=== ('''***NOT YET IMPLEMENTED***''') Bitcraze is currently working on adding a state estimator onto the Firmware to handle control calculations instead of the PID. The code is in place but the controller is not yet used as of '''7/13/16'''. == PC Client == === PID Controllers (Position and Yaw) === The first controller implemented on the Client were 4 PID controllers used to stabilize the Crazyflie's position in X, Y, and Z, as well as angular position in Yaw respectively. These PID's feed directly into the Firmware PID's as seen here: [[Image:CompletePIDArchitectureFigure.png|500px]] The controllers inside the red box are the original PID controllers located on the Firmware as shown above in the [[#Original PID Controllers (Angular Rotation)|Original PID's]]. ====Initialize the PID's==== :1. To start we create a struct with all the necessary variables (code from ''pid.h''): <blockquote> <code> <pre> typedef struct { float desired; //< set point float error; //< error float prevError; //< previous error float integ; //< integral float deriv; //< derivative float kp; //< proportional gain float ki; //< integral gain float kd; //< derivative gain float outP; //< proportional output (debugging) float outI; //< integral output (debugging) float outD; //< derivative output (debugging) float iLimit; //< integral limit float iLimitLow; //< integral limit float dt; //< delta-time dt float angularLimit; //sets limit for how far Crazyflie can tip, to prevent flipping float angularLimitLow; //^ float thrustLimit; //Sets upper limit for Thrust Output (60000?) **? float thrustLimitLow; //Sets lower limit for thrust Output (10001) } PidObject; </pre> </code> </blockquote> :2. To simplify scaling up the code to multiple Crazyflies, we will create a <code> ControllerObject </code> that contains multiple PID structs as shown (code in ''controller.h''): <blockquote> <code> <pre> typedef struct { PidObject pidRoll; PidObject pidPitch; PidObject pidYaw; PidObject pidX; PidObject pidY; PidObject pidZ; bool isInit; } ControllerObject; </pre> </code> </blockquote> :3. Then we initialize the Objects to 0 at the start of each run (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> ControllerObject pidCtrl1 = { 0 }; // init all fields to zero ControllerObject pidCtrl2 = { 0 }; // init all fields to zero ControllerObject pidCtrl3 = { 0 }; // init all fields to zero ControllerObject pidCtrl4 = { 0 }; // init all fields to zero </pre> </code> </blockquote> :4. Then populate the PidObjects with the desired parameters (code in ''pid.c''): <blockquote> <code> <pre> void pidInit(PidObject* pid, const float desired, const float kp, const float ki, const float kd, const float dt) { pid->error = 0; pid->prevError = 0; pid->integ = 0; pid->deriv = 0; pid->desired = desired; pid->kp = kp; pid->ki = ki; pid->kd = kd; pid->iLimit = DEFAULT_PID_INTEGRATION_LIMIT; pid->iLimitLow = -DEFAULT_PID_INTEGRATION_LIMIT; pid->angularLimit = DEFAULT_PID_ANGLE_OUTPUT; pid->angularLimitLow = -DEFAULT_PID_ANGLE_OUTPUT; pid->thrustLimit = DEFAULT_PID_HIGH_THRUST_LIMIT; pid->thrustLimitLow = DEFAULT_PID_LOW_THRUST_LIMIT; pid->dt = dt; } </pre> </code> </blockquote> Using the above function for each of the <code>PidObjects</code> inside of the <code>ControllerObject</code> below (code in ''controller.c''): <blockquote> <code> <pre> void controllerInit( ControllerObject * ctrl ) { if(ctrl->isInit) return; pidInit(&ctrl->pidY, 0, PID_Y_KP, PID_Y_KI, PID_Y_KD, CAMERA_UPDATE_DT); //for Roll PID pidInit(&ctrl->pidX, 0, PID_X_KP, PID_X_KI, PID_X_KD, CAMERA_UPDATE_DT); //for Pitch PID pidInit(&ctrl->pidYaw, 0, PID_YAW_KP, PID_YAW_KI, PID_YAW_KD, CAMERA_UPDATE_DT); pidInit(&ctrl->pidZ, 0, PID_Z_KP, PID_Z_KI, PID_Z_KD, CAMERA_UPDATE_DT); pidSetIntegralLimit(&ctrl->pidY, PID_Y_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidX, PID_X_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidYaw, PID_YAW_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidZ, PID_Z_INTEGRATION_LIMIT); ctrl->isInit = true; } </pre> </code> </blockquote> '''Note:''' If we have multiple Crazyflies we need a <code>ControllerObject</code> for each Crazyflie (code in ''eris_vrpn.cpp'') <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl1 ); controllerInit( &pidCtrl1 ); #endif #if NUM_QUADS >= 2 controllerResetAllPID( &pidCtrl2 ); controllerInit( &pidCtrl2 ); #endif #if NUM_QUADS >=3 controllerResetAllPID( &pidCtrl3 ); controllerInit( &pidCtrl3 ); #endif #if NUM_QUADS >=4 controllerResetAllPID( &pidCtrl4 ); controllerInit( &pidCtrl4 ); #endif </pre> </code> </blockquote> Now the initialization of the Controllers is complete. ====Calculating the PID's==== :1. Each loop we want to calculate the PID output (code in ''pid.c''): <blockquote> <code> <pre> float pidUpdateAngle(PidObject* pid, const float measured, const bool updateError) //**USED FOR ATTITUDE CONTROL { float output; if(updateError) { pid->error = pid->desired - measured; //Calculates current error } pid->integ += pid->error * pid->dt; //Calculates integral term if(pid->integ > pid->iLimit) //Checks that the integral term stays below the integral limit (anti-windup) { pid->integ = pid->iLimit; } else if(pid->integ < pid->iLimitLow) { pid->integ = pid->iLimitLow; } pid->deriv = (pid->error - pid->prevError) / pid->dt; //Calculates derivative term pid->outP = pid->kp* pid->error; pid->outI = pid->ki * pid->integ; pid->outD = pid->kd * pid->deriv; output = pid->outP + pid->outI + pid->outD; //Adds up all 3 calculated terms for output if(output > pid->angularLimit) //Limits amount Crazyflie can tip { output = pid->angularLimit; } if(output < pid->angularLimitLow) //Limits amount Crazyflie can tip { output = pid->angularLimitLow; } pid->prevError = pid->error; //Stores the current error for next loop return output; } </pre> </code> </blockquote> '''Note:''' There are 3 different versions of this Function (for Angle, Thrust, and Yaw) since each has different output limits. :2. Using the function above, combine all PID calculations into one function (code in ''controller.c''): <blockquote> <code> <pre> void controllerCorrectAttitudePID(ControllerObject * ctrl, float xPositionActual, float yPositionActual, float zPositionActual, float eulerYawActual, float xPositionDesired, float yPositionDesired, float zPositionDesired, float eulerYawDesired, float* rollControlOutput, float* pitchControlOutput, float* yawControlOutput, float* thrustControlOutput) { pidSetDesired(&ctrl->pidX, xPositionDesired); *pitchControlOutput = pidUpdateAngle(&ctrl->pidX, xPositionActual, false); //Originally true pidSetDesired(&ctrl->pidY, yPositionDesired); *rollControlOutput = pidUpdateAngle(&ctrl->pidY, yPositionActual, false); //Originally true pidSetDesired(&ctrl->pidZ, zPositionDesired); *thrustControlOutput = pidUpdateThrust(&ctrl->pidZ,zPositionActual, true); float yawError; pidSetDesired(&ctrl->pidYaw, eulerYawDesired); yawError = eulerYawDesired - eulerYawActual; if(yawError > 180.0) //Ensures Yaw error stays between -180 and 180 degrees yawError -= 360.0; else if(yawError < -180.0) yawError += 360.0; pidSetError(&ctrl->pidYaw, yawError); *yawControlOutput = pidUpdateYaw(&ctrl->pidYaw, eulerYawActual, true); //originally false } </pre> </code> </blockquote> :3. In each Callback, calculate the Controller outputs, assigned to pointer values<code>*rollControlOutput</code>, <code>*pitchControlOutput</code>, etc... (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; //Calculates error externally controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); </pre> </code> </blockquote> '''Note:''' We calculate error externally for X and Y because certain swarm controllers need special setpoint modifiers (this way we can switch modes without effecting the default setpoint): '''Example:''' Follow Hand Mode Error (Crazyflie1 will have setpoint -0.5 m lower in X and +0.5 m higher in Y than your hand trackable): <blockquote> <code> <pre> ... xError1 = (xPositionHand - 0.5) - xPosition1; yError1 = (yPositionHand + 0.5) - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); ... </pre> </code> </blockquote> :4. Repeat for each set of new location data. 097552286225855ba1806eeae56521bd0223ec5d 66 65 2016-07-13T17:46:50Z Jnoronha 3 wikitext text/x-wiki The Crazyflie platform is completely customizable when it comes to the control design. As long as the controller can be written in C or C++, we can implement it in the Platform. This applies to both the controllers run on the PC Client and the controllers run on the Firmware of the Crazyflie. Originally the only controllers in the Platform were Firmware PID's that controlled the angular position and rates of the Crazyflie for hand flight. The original controller layout can be seen in '''Figure 1'''. Below you will find documentation on the different types of Controllers that have been applied to the platform, organized by their location in the Platform. == Firmware == === Original PID Controllers (Angular Rotation) === Directly on the Crazyflie Firmware there are 5 PID controllers as seen here: [[Image:FirmwareOnlyPIDArchitecture.png|500px]] The Pitch and Roll angular position PID's receive constant setpoints from some outside source (gamepad controller or automated controller). The outputs of those angular position controllers is then fed into the angular rate controllers as shown. This final output is then fed into the Motor Command block which converts the angular rate setpoints into motor commands. ---- ===State Estimator=== ('''***NOT YET IMPLEMENTED***''') Bitcraze is currently working on adding a state estimator onto the Firmware to handle control calculations instead of the PID. The code is in place but the controller is not yet used as of '''7/13/16'''. == PC Client == === PID Controllers (Position and Yaw) === The first controller implemented on the Client were 4 PID controllers used to stabilize the Crazyflie's position in X, Y, and Z, and angular position in Yaw respectively. These PID's feed directly into the Firmware PID's as seen here: [[Image:CompletePIDArchitectureFigure.png|500px]] The controllers inside the red box are the original PID controllers located on the Firmware as shown above in the [[#Original PID Controllers (Angular Rotation)|Original PID's]]. ====Initialize the PID's==== :1. To start we create a struct with all the necessary variables (code from ''pid.h''): <blockquote> <code> <pre> typedef struct { float desired; //< set point float error; //< error float prevError; //< previous error float integ; //< integral float deriv; //< derivative float kp; //< proportional gain float ki; //< integral gain float kd; //< derivative gain float outP; //< proportional output (debugging) float outI; //< integral output (debugging) float outD; //< derivative output (debugging) float iLimit; //< integral limit float iLimitLow; //< integral limit float dt; //< delta-time dt float angularLimit; //sets limit for how far Crazyflie can tip, to prevent flipping float angularLimitLow; //^ float thrustLimit; //Sets upper limit for Thrust Output (60000?) **? float thrustLimitLow; //Sets lower limit for thrust Output (10001) } PidObject; </pre> </code> </blockquote> :2. To simplify scaling up the code to multiple Crazyflies, we will create a <code> ControllerObject </code> that contains multiple PID structs as shown (code in ''controller.h''): <blockquote> <code> <pre> typedef struct { PidObject pidRoll; PidObject pidPitch; PidObject pidYaw; PidObject pidX; PidObject pidY; PidObject pidZ; bool isInit; } ControllerObject; </pre> </code> </blockquote> :3. Then we initialize the Objects to 0 at the start of each run (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> ControllerObject pidCtrl1 = { 0 }; // init all fields to zero ControllerObject pidCtrl2 = { 0 }; // init all fields to zero ControllerObject pidCtrl3 = { 0 }; // init all fields to zero ControllerObject pidCtrl4 = { 0 }; // init all fields to zero </pre> </code> </blockquote> :4. Then populate the PidObjects with the desired parameters (code in ''pid.c''): <blockquote> <code> <pre> void pidInit(PidObject* pid, const float desired, const float kp, const float ki, const float kd, const float dt) { pid->error = 0; pid->prevError = 0; pid->integ = 0; pid->deriv = 0; pid->desired = desired; pid->kp = kp; pid->ki = ki; pid->kd = kd; pid->iLimit = DEFAULT_PID_INTEGRATION_LIMIT; pid->iLimitLow = -DEFAULT_PID_INTEGRATION_LIMIT; pid->angularLimit = DEFAULT_PID_ANGLE_OUTPUT; pid->angularLimitLow = -DEFAULT_PID_ANGLE_OUTPUT; pid->thrustLimit = DEFAULT_PID_HIGH_THRUST_LIMIT; pid->thrustLimitLow = DEFAULT_PID_LOW_THRUST_LIMIT; pid->dt = dt; } </pre> </code> </blockquote> Using the above function for each of the <code>PidObjects</code> inside of the <code>ControllerObject</code> below (code in ''controller.c''): <blockquote> <code> <pre> void controllerInit( ControllerObject * ctrl ) { if(ctrl->isInit) return; pidInit(&ctrl->pidY, 0, PID_Y_KP, PID_Y_KI, PID_Y_KD, CAMERA_UPDATE_DT); //for Roll PID pidInit(&ctrl->pidX, 0, PID_X_KP, PID_X_KI, PID_X_KD, CAMERA_UPDATE_DT); //for Pitch PID pidInit(&ctrl->pidYaw, 0, PID_YAW_KP, PID_YAW_KI, PID_YAW_KD, CAMERA_UPDATE_DT); pidInit(&ctrl->pidZ, 0, PID_Z_KP, PID_Z_KI, PID_Z_KD, CAMERA_UPDATE_DT); pidSetIntegralLimit(&ctrl->pidY, PID_Y_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidX, PID_X_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidYaw, PID_YAW_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidZ, PID_Z_INTEGRATION_LIMIT); ctrl->isInit = true; } </pre> </code> </blockquote> '''Note:''' If we have multiple Crazyflies we need a <code>ControllerObject</code> for each Crazyflie (code in ''eris_vrpn.cpp'') <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl1 ); controllerInit( &pidCtrl1 ); #endif #if NUM_QUADS >= 2 controllerResetAllPID( &pidCtrl2 ); controllerInit( &pidCtrl2 ); #endif #if NUM_QUADS >=3 controllerResetAllPID( &pidCtrl3 ); controllerInit( &pidCtrl3 ); #endif #if NUM_QUADS >=4 controllerResetAllPID( &pidCtrl4 ); controllerInit( &pidCtrl4 ); #endif </pre> </code> </blockquote> Now the initialization of the Controllers is complete. ====Calculating the PID's==== :1. Each loop we want to calculate the PID output (code in ''pid.c''): <blockquote> <code> <pre> float pidUpdateAngle(PidObject* pid, const float measured, const bool updateError) //**USED FOR ATTITUDE CONTROL { float output; if(updateError) { pid->error = pid->desired - measured; //Calculates current error } pid->integ += pid->error * pid->dt; //Calculates integral term if(pid->integ > pid->iLimit) //Checks that the integral term stays below the integral limit (anti-windup) { pid->integ = pid->iLimit; } else if(pid->integ < pid->iLimitLow) { pid->integ = pid->iLimitLow; } pid->deriv = (pid->error - pid->prevError) / pid->dt; //Calculates derivative term pid->outP = pid->kp* pid->error; pid->outI = pid->ki * pid->integ; pid->outD = pid->kd * pid->deriv; output = pid->outP + pid->outI + pid->outD; //Adds up all 3 calculated terms for output if(output > pid->angularLimit) //Limits amount Crazyflie can tip { output = pid->angularLimit; } if(output < pid->angularLimitLow) //Limits amount Crazyflie can tip { output = pid->angularLimitLow; } pid->prevError = pid->error; //Stores the current error for next loop return output; } </pre> </code> </blockquote> '''Note:''' There are 3 different versions of this Function (for Angle, Thrust, and Yaw) since each has different output limits. :2. Using the function above, combine all PID calculations into one function (code in ''controller.c''): <blockquote> <code> <pre> void controllerCorrectAttitudePID(ControllerObject * ctrl, float xPositionActual, float yPositionActual, float zPositionActual, float eulerYawActual, float xPositionDesired, float yPositionDesired, float zPositionDesired, float eulerYawDesired, float* rollControlOutput, float* pitchControlOutput, float* yawControlOutput, float* thrustControlOutput) { pidSetDesired(&ctrl->pidX, xPositionDesired); *pitchControlOutput = pidUpdateAngle(&ctrl->pidX, xPositionActual, false); //Originally true pidSetDesired(&ctrl->pidY, yPositionDesired); *rollControlOutput = pidUpdateAngle(&ctrl->pidY, yPositionActual, false); //Originally true pidSetDesired(&ctrl->pidZ, zPositionDesired); *thrustControlOutput = pidUpdateThrust(&ctrl->pidZ,zPositionActual, true); float yawError; pidSetDesired(&ctrl->pidYaw, eulerYawDesired); yawError = eulerYawDesired - eulerYawActual; if(yawError > 180.0) //Ensures Yaw error stays between -180 and 180 degrees yawError -= 360.0; else if(yawError < -180.0) yawError += 360.0; pidSetError(&ctrl->pidYaw, yawError); *yawControlOutput = pidUpdateYaw(&ctrl->pidYaw, eulerYawActual, true); //originally false } </pre> </code> </blockquote> :3. In each Callback, calculate the Controller outputs, assigned to pointer values<code>*rollControlOutput</code>, <code>*pitchControlOutput</code>, etc... (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; //Calculates error externally controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); </pre> </code> </blockquote> '''Note:''' We calculate error externally for X and Y because certain swarm controllers need special setpoint modifiers (this way we can switch modes without effecting the default setpoint): '''Example:''' Follow Hand Mode Error (Crazyflie1 will have setpoint -0.5 m lower in X and +0.5 m higher in Y than your hand trackable): <blockquote> <code> <pre> ... xError1 = (xPositionHand - 0.5) - xPosition1; yError1 = (yPositionHand + 0.5) - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); ... </pre> </code> </blockquote> :4. Repeat for each set of new location data. 9de61c4ba3883cb9a7913c4ddd2e2d251ff75a7f 67 66 2016-07-13T17:48:10Z Jnoronha 3 Replaced figure 1 link with Original PID's header link wikitext text/x-wiki The Crazyflie platform is completely customizable when it comes to the control design. As long as the controller can be written in C or C++, we can implement it in the Platform. This applies to both the controllers run on the PC Client and the controllers run on the Firmware of the Crazyflie. Originally the only controllers in the Platform were Firmware PID's that controlled the angular position and rates of the Crazyflie for hand flight. The original controller layout can be seen here [[#Original PID Controllers (Angular Rotation)|Original PID's]]. Below you will find documentation on the different types of Controllers that have been applied to the platform, organized by their location in the Platform. == Firmware == === Original PID Controllers (Angular Rotation) === Directly on the Crazyflie Firmware there are 5 PID controllers as seen here: [[Image:FirmwareOnlyPIDArchitecture.png|500px]] The Pitch and Roll angular position PID's receive constant setpoints from some outside source (gamepad controller or automated controller). The outputs of those angular position controllers is then fed into the angular rate controllers as shown. This final output is then fed into the Motor Command block which converts the angular rate setpoints into motor commands. ---- ===State Estimator=== ('''***NOT YET IMPLEMENTED***''') Bitcraze is currently working on adding a state estimator onto the Firmware to handle control calculations instead of the PID. The code is in place but the controller is not yet used as of '''7/13/16'''. == PC Client == === PID Controllers (Position and Yaw) === The first controller implemented on the Client were 4 PID controllers used to stabilize the Crazyflie's position in X, Y, and Z, and angular position in Yaw respectively. These PID's feed directly into the Firmware PID's as seen here: [[Image:CompletePIDArchitectureFigure.png|500px]] The controllers inside the red box are the original PID controllers located on the Firmware as shown above in the [[#Original PID Controllers (Angular Rotation)|Original PID's]]. ====Initialize the PID's==== :1. To start we create a struct with all the necessary variables (code from ''pid.h''): <blockquote> <code> <pre> typedef struct { float desired; //< set point float error; //< error float prevError; //< previous error float integ; //< integral float deriv; //< derivative float kp; //< proportional gain float ki; //< integral gain float kd; //< derivative gain float outP; //< proportional output (debugging) float outI; //< integral output (debugging) float outD; //< derivative output (debugging) float iLimit; //< integral limit float iLimitLow; //< integral limit float dt; //< delta-time dt float angularLimit; //sets limit for how far Crazyflie can tip, to prevent flipping float angularLimitLow; //^ float thrustLimit; //Sets upper limit for Thrust Output (60000?) **? float thrustLimitLow; //Sets lower limit for thrust Output (10001) } PidObject; </pre> </code> </blockquote> :2. To simplify scaling up the code to multiple Crazyflies, we will create a <code> ControllerObject </code> that contains multiple PID structs as shown (code in ''controller.h''): <blockquote> <code> <pre> typedef struct { PidObject pidRoll; PidObject pidPitch; PidObject pidYaw; PidObject pidX; PidObject pidY; PidObject pidZ; bool isInit; } ControllerObject; </pre> </code> </blockquote> :3. Then we initialize the Objects to 0 at the start of each run (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> ControllerObject pidCtrl1 = { 0 }; // init all fields to zero ControllerObject pidCtrl2 = { 0 }; // init all fields to zero ControllerObject pidCtrl3 = { 0 }; // init all fields to zero ControllerObject pidCtrl4 = { 0 }; // init all fields to zero </pre> </code> </blockquote> :4. Then populate the PidObjects with the desired parameters (code in ''pid.c''): <blockquote> <code> <pre> void pidInit(PidObject* pid, const float desired, const float kp, const float ki, const float kd, const float dt) { pid->error = 0; pid->prevError = 0; pid->integ = 0; pid->deriv = 0; pid->desired = desired; pid->kp = kp; pid->ki = ki; pid->kd = kd; pid->iLimit = DEFAULT_PID_INTEGRATION_LIMIT; pid->iLimitLow = -DEFAULT_PID_INTEGRATION_LIMIT; pid->angularLimit = DEFAULT_PID_ANGLE_OUTPUT; pid->angularLimitLow = -DEFAULT_PID_ANGLE_OUTPUT; pid->thrustLimit = DEFAULT_PID_HIGH_THRUST_LIMIT; pid->thrustLimitLow = DEFAULT_PID_LOW_THRUST_LIMIT; pid->dt = dt; } </pre> </code> </blockquote> Using the above function for each of the <code>PidObjects</code> inside of the <code>ControllerObject</code> below (code in ''controller.c''): <blockquote> <code> <pre> void controllerInit( ControllerObject * ctrl ) { if(ctrl->isInit) return; pidInit(&ctrl->pidY, 0, PID_Y_KP, PID_Y_KI, PID_Y_KD, CAMERA_UPDATE_DT); //for Roll PID pidInit(&ctrl->pidX, 0, PID_X_KP, PID_X_KI, PID_X_KD, CAMERA_UPDATE_DT); //for Pitch PID pidInit(&ctrl->pidYaw, 0, PID_YAW_KP, PID_YAW_KI, PID_YAW_KD, CAMERA_UPDATE_DT); pidInit(&ctrl->pidZ, 0, PID_Z_KP, PID_Z_KI, PID_Z_KD, CAMERA_UPDATE_DT); pidSetIntegralLimit(&ctrl->pidY, PID_Y_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidX, PID_X_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidYaw, PID_YAW_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidZ, PID_Z_INTEGRATION_LIMIT); ctrl->isInit = true; } </pre> </code> </blockquote> '''Note:''' If we have multiple Crazyflies we need a <code>ControllerObject</code> for each Crazyflie (code in ''eris_vrpn.cpp'') <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl1 ); controllerInit( &pidCtrl1 ); #endif #if NUM_QUADS >= 2 controllerResetAllPID( &pidCtrl2 ); controllerInit( &pidCtrl2 ); #endif #if NUM_QUADS >=3 controllerResetAllPID( &pidCtrl3 ); controllerInit( &pidCtrl3 ); #endif #if NUM_QUADS >=4 controllerResetAllPID( &pidCtrl4 ); controllerInit( &pidCtrl4 ); #endif </pre> </code> </blockquote> Now the initialization of the Controllers is complete. ====Calculating the PID's==== :1. Each loop we want to calculate the PID output (code in ''pid.c''): <blockquote> <code> <pre> float pidUpdateAngle(PidObject* pid, const float measured, const bool updateError) //**USED FOR ATTITUDE CONTROL { float output; if(updateError) { pid->error = pid->desired - measured; //Calculates current error } pid->integ += pid->error * pid->dt; //Calculates integral term if(pid->integ > pid->iLimit) //Checks that the integral term stays below the integral limit (anti-windup) { pid->integ = pid->iLimit; } else if(pid->integ < pid->iLimitLow) { pid->integ = pid->iLimitLow; } pid->deriv = (pid->error - pid->prevError) / pid->dt; //Calculates derivative term pid->outP = pid->kp* pid->error; pid->outI = pid->ki * pid->integ; pid->outD = pid->kd * pid->deriv; output = pid->outP + pid->outI + pid->outD; //Adds up all 3 calculated terms for output if(output > pid->angularLimit) //Limits amount Crazyflie can tip { output = pid->angularLimit; } if(output < pid->angularLimitLow) //Limits amount Crazyflie can tip { output = pid->angularLimitLow; } pid->prevError = pid->error; //Stores the current error for next loop return output; } </pre> </code> </blockquote> '''Note:''' There are 3 different versions of this Function (for Angle, Thrust, and Yaw) since each has different output limits. :2. Using the function above, combine all PID calculations into one function (code in ''controller.c''): <blockquote> <code> <pre> void controllerCorrectAttitudePID(ControllerObject * ctrl, float xPositionActual, float yPositionActual, float zPositionActual, float eulerYawActual, float xPositionDesired, float yPositionDesired, float zPositionDesired, float eulerYawDesired, float* rollControlOutput, float* pitchControlOutput, float* yawControlOutput, float* thrustControlOutput) { pidSetDesired(&ctrl->pidX, xPositionDesired); *pitchControlOutput = pidUpdateAngle(&ctrl->pidX, xPositionActual, false); //Originally true pidSetDesired(&ctrl->pidY, yPositionDesired); *rollControlOutput = pidUpdateAngle(&ctrl->pidY, yPositionActual, false); //Originally true pidSetDesired(&ctrl->pidZ, zPositionDesired); *thrustControlOutput = pidUpdateThrust(&ctrl->pidZ,zPositionActual, true); float yawError; pidSetDesired(&ctrl->pidYaw, eulerYawDesired); yawError = eulerYawDesired - eulerYawActual; if(yawError > 180.0) //Ensures Yaw error stays between -180 and 180 degrees yawError -= 360.0; else if(yawError < -180.0) yawError += 360.0; pidSetError(&ctrl->pidYaw, yawError); *yawControlOutput = pidUpdateYaw(&ctrl->pidYaw, eulerYawActual, true); //originally false } </pre> </code> </blockquote> :3. In each Callback, calculate the Controller outputs, assigned to pointer values<code>*rollControlOutput</code>, <code>*pitchControlOutput</code>, etc... (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; //Calculates error externally controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); </pre> </code> </blockquote> '''Note:''' We calculate error externally for X and Y because certain swarm controllers need special setpoint modifiers (this way we can switch modes without effecting the default setpoint): '''Example:''' Follow Hand Mode Error (Crazyflie1 will have setpoint -0.5 m lower in X and +0.5 m higher in Y than your hand trackable): <blockquote> <code> <pre> ... xError1 = (xPositionHand - 0.5) - xPosition1; yError1 = (yPositionHand + 0.5) - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); ... </pre> </code> </blockquote> :4. Repeat for each set of new location data. 1e1f42f0310ed1276e37432b6aa87216f52d121b 68 67 2016-07-13T18:06:26Z Jnoronha 3 Finally figured out sub-section linking for the Directory footer wikitext text/x-wiki The Crazyflie platform is completely customizable when it comes to the control design. As long as the controller can be written in C or C++, we can implement it in the Platform. This applies to both the controllers run on the PC Client and the controllers run on the Firmware of the Crazyflie. Originally the only controllers in the Platform were Firmware PID's that controlled the angular position and rates of the Crazyflie for hand flight. The original controller layout can be seen here [[#Original PID Controllers (Angular Rotation)|Original PID's]]. Below you will find documentation on the different types of Controllers that have been applied to the platform, organized by their location in the Platform. == Firmware == === Original PID Controllers (Angular Rotation) === Directly on the Crazyflie Firmware there are 5 PID controllers as seen here: [[Image:FirmwareOnlyPIDArchitecture.png|500px]] The Pitch and Roll angular position PID's receive constant setpoints from some outside source (gamepad controller or automated controller). The outputs of those angular position controllers is then fed into the angular rate controllers as shown. This final output is then fed into the Motor Command block which converts the angular rate setpoints into motor commands. ---- ===State Estimator=== ('''***NOT YET IMPLEMENTED***''') Bitcraze is currently working on adding a state estimator onto the Firmware to handle control calculations instead of the PID. The code is in place but the controller is not yet used as of '''7/13/16'''. == PC Client == === PID Controllers (Position and Yaw) === The first controller implemented on the Client were 4 PID controllers used to stabilize the Crazyflie's position in X, Y, and Z, and angular position in Yaw respectively. These PID's feed directly into the Firmware PID's as seen here: [[Image:CompletePIDArchitectureFigure.png|500px]] The controllers inside the red box are the original PID controllers located on the Firmware as shown above in the [[#Original PID Controllers (Angular Rotation)|Original PID's]]. ====Initialize the PID's==== :1. To start we create a struct with all the necessary variables (code from ''pid.h''): <blockquote> <code> <pre> typedef struct { float desired; //< set point float error; //< error float prevError; //< previous error float integ; //< integral float deriv; //< derivative float kp; //< proportional gain float ki; //< integral gain float kd; //< derivative gain float outP; //< proportional output (debugging) float outI; //< integral output (debugging) float outD; //< derivative output (debugging) float iLimit; //< integral limit float iLimitLow; //< integral limit float dt; //< delta-time dt float angularLimit; //sets limit for how far Crazyflie can tip, to prevent flipping float angularLimitLow; //^ float thrustLimit; //Sets upper limit for Thrust Output (60000?) **? float thrustLimitLow; //Sets lower limit for thrust Output (10001) } PidObject; </pre> </code> </blockquote> :2. To simplify scaling up the code to multiple Crazyflies, we will create a <code> ControllerObject </code> that contains multiple PID structs as shown (code in ''controller.h''): <blockquote> <code> <pre> typedef struct { PidObject pidRoll; PidObject pidPitch; PidObject pidYaw; PidObject pidX; PidObject pidY; PidObject pidZ; bool isInit; } ControllerObject; </pre> </code> </blockquote> :3. Then we initialize the Objects to 0 at the start of each run (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> ControllerObject pidCtrl1 = { 0 }; // init all fields to zero ControllerObject pidCtrl2 = { 0 }; // init all fields to zero ControllerObject pidCtrl3 = { 0 }; // init all fields to zero ControllerObject pidCtrl4 = { 0 }; // init all fields to zero </pre> </code> </blockquote> :4. Then populate the PidObjects with the desired parameters (code in ''pid.c''): <blockquote> <code> <pre> void pidInit(PidObject* pid, const float desired, const float kp, const float ki, const float kd, const float dt) { pid->error = 0; pid->prevError = 0; pid->integ = 0; pid->deriv = 0; pid->desired = desired; pid->kp = kp; pid->ki = ki; pid->kd = kd; pid->iLimit = DEFAULT_PID_INTEGRATION_LIMIT; pid->iLimitLow = -DEFAULT_PID_INTEGRATION_LIMIT; pid->angularLimit = DEFAULT_PID_ANGLE_OUTPUT; pid->angularLimitLow = -DEFAULT_PID_ANGLE_OUTPUT; pid->thrustLimit = DEFAULT_PID_HIGH_THRUST_LIMIT; pid->thrustLimitLow = DEFAULT_PID_LOW_THRUST_LIMIT; pid->dt = dt; } </pre> </code> </blockquote> Using the above function for each of the <code>PidObjects</code> inside of the <code>ControllerObject</code> below (code in ''controller.c''): <blockquote> <code> <pre> void controllerInit( ControllerObject * ctrl ) { if(ctrl->isInit) return; pidInit(&ctrl->pidY, 0, PID_Y_KP, PID_Y_KI, PID_Y_KD, CAMERA_UPDATE_DT); //for Roll PID pidInit(&ctrl->pidX, 0, PID_X_KP, PID_X_KI, PID_X_KD, CAMERA_UPDATE_DT); //for Pitch PID pidInit(&ctrl->pidYaw, 0, PID_YAW_KP, PID_YAW_KI, PID_YAW_KD, CAMERA_UPDATE_DT); pidInit(&ctrl->pidZ, 0, PID_Z_KP, PID_Z_KI, PID_Z_KD, CAMERA_UPDATE_DT); pidSetIntegralLimit(&ctrl->pidY, PID_Y_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidX, PID_X_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidYaw, PID_YAW_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidZ, PID_Z_INTEGRATION_LIMIT); ctrl->isInit = true; } </pre> </code> </blockquote> '''Note:''' If we have multiple Crazyflies we need a <code>ControllerObject</code> for each Crazyflie (code in ''eris_vrpn.cpp'') <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl1 ); controllerInit( &pidCtrl1 ); #endif #if NUM_QUADS >= 2 controllerResetAllPID( &pidCtrl2 ); controllerInit( &pidCtrl2 ); #endif #if NUM_QUADS >=3 controllerResetAllPID( &pidCtrl3 ); controllerInit( &pidCtrl3 ); #endif #if NUM_QUADS >=4 controllerResetAllPID( &pidCtrl4 ); controllerInit( &pidCtrl4 ); #endif </pre> </code> </blockquote> Now the initialization of the Controllers is complete. ====Calculating the PID's==== :1. Each loop we want to calculate the PID output (code in ''pid.c''): <blockquote> <code> <pre> float pidUpdateAngle(PidObject* pid, const float measured, const bool updateError) //**USED FOR ATTITUDE CONTROL { float output; if(updateError) { pid->error = pid->desired - measured; //Calculates current error } pid->integ += pid->error * pid->dt; //Calculates integral term if(pid->integ > pid->iLimit) //Checks that the integral term stays below the integral limit (anti-windup) { pid->integ = pid->iLimit; } else if(pid->integ < pid->iLimitLow) { pid->integ = pid->iLimitLow; } pid->deriv = (pid->error - pid->prevError) / pid->dt; //Calculates derivative term pid->outP = pid->kp* pid->error; pid->outI = pid->ki * pid->integ; pid->outD = pid->kd * pid->deriv; output = pid->outP + pid->outI + pid->outD; //Adds up all 3 calculated terms for output if(output > pid->angularLimit) //Limits amount Crazyflie can tip { output = pid->angularLimit; } if(output < pid->angularLimitLow) //Limits amount Crazyflie can tip { output = pid->angularLimitLow; } pid->prevError = pid->error; //Stores the current error for next loop return output; } </pre> </code> </blockquote> '''Note:''' There are 3 different versions of this Function (for Angle, Thrust, and Yaw) since each has different output limits. :2. Using the function above, combine all PID calculations into one function (code in ''controller.c''): <blockquote> <code> <pre> void controllerCorrectAttitudePID(ControllerObject * ctrl, float xPositionActual, float yPositionActual, float zPositionActual, float eulerYawActual, float xPositionDesired, float yPositionDesired, float zPositionDesired, float eulerYawDesired, float* rollControlOutput, float* pitchControlOutput, float* yawControlOutput, float* thrustControlOutput) { pidSetDesired(&ctrl->pidX, xPositionDesired); *pitchControlOutput = pidUpdateAngle(&ctrl->pidX, xPositionActual, false); //Originally true pidSetDesired(&ctrl->pidY, yPositionDesired); *rollControlOutput = pidUpdateAngle(&ctrl->pidY, yPositionActual, false); //Originally true pidSetDesired(&ctrl->pidZ, zPositionDesired); *thrustControlOutput = pidUpdateThrust(&ctrl->pidZ,zPositionActual, true); float yawError; pidSetDesired(&ctrl->pidYaw, eulerYawDesired); yawError = eulerYawDesired - eulerYawActual; if(yawError > 180.0) //Ensures Yaw error stays between -180 and 180 degrees yawError -= 360.0; else if(yawError < -180.0) yawError += 360.0; pidSetError(&ctrl->pidYaw, yawError); *yawControlOutput = pidUpdateYaw(&ctrl->pidYaw, eulerYawActual, true); //originally false } </pre> </code> </blockquote> :3. In each Callback, calculate the Controller outputs, assigned to pointer values<code>*rollControlOutput</code>, <code>*pitchControlOutput</code>, etc... (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; //Calculates error externally controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); </pre> </code> </blockquote> '''Note:''' We calculate error externally for X and Y because certain swarm controllers need special setpoint modifiers (this way we can switch modes without effecting the default setpoint): '''Example:''' Follow Hand Mode Error (Crazyflie1 will have setpoint -0.5 m lower in X and +0.5 m higher in Y than your hand trackable): <blockquote> <code> <pre> ... xError1 = (xPositionHand - 0.5) - xPosition1; yError1 = (yPositionHand + 0.5) - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); ... </pre> </code> </blockquote> :4. Repeat for each set of new location data. ---- <center> '''Modifications Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> e95ff224b5a54fa5b3eb4dce7699fa1761974710 69 68 2016-07-13T18:07:39Z Jnoronha 3 spaced the directory footer better wikitext text/x-wiki The Crazyflie platform is completely customizable when it comes to the control design. As long as the controller can be written in C or C++, we can implement it in the Platform. This applies to both the controllers run on the PC Client and the controllers run on the Firmware of the Crazyflie. Originally the only controllers in the Platform were Firmware PID's that controlled the angular position and rates of the Crazyflie for hand flight. The original controller layout can be seen here [[#Original PID Controllers (Angular Rotation)|Original PID's]]. Below you will find documentation on the different types of Controllers that have been applied to the platform, organized by their location in the Platform. == Firmware == === Original PID Controllers (Angular Rotation) === Directly on the Crazyflie Firmware there are 5 PID controllers as seen here: [[Image:FirmwareOnlyPIDArchitecture.png|500px]] The Pitch and Roll angular position PID's receive constant setpoints from some outside source (gamepad controller or automated controller). The outputs of those angular position controllers is then fed into the angular rate controllers as shown. This final output is then fed into the Motor Command block which converts the angular rate setpoints into motor commands. ---- ===State Estimator=== ('''***NOT YET IMPLEMENTED***''') Bitcraze is currently working on adding a state estimator onto the Firmware to handle control calculations instead of the PID. The code is in place but the controller is not yet used as of '''7/13/16'''. == PC Client == === PID Controllers (Position and Yaw) === The first controller implemented on the Client were 4 PID controllers used to stabilize the Crazyflie's position in X, Y, and Z, and angular position in Yaw respectively. These PID's feed directly into the Firmware PID's as seen here: [[Image:CompletePIDArchitectureFigure.png|500px]] The controllers inside the red box are the original PID controllers located on the Firmware as shown above in the [[#Original PID Controllers (Angular Rotation)|Original PID's]]. ====Initialize the PID's==== :1. To start we create a struct with all the necessary variables (code from ''pid.h''): <blockquote> <code> <pre> typedef struct { float desired; //< set point float error; //< error float prevError; //< previous error float integ; //< integral float deriv; //< derivative float kp; //< proportional gain float ki; //< integral gain float kd; //< derivative gain float outP; //< proportional output (debugging) float outI; //< integral output (debugging) float outD; //< derivative output (debugging) float iLimit; //< integral limit float iLimitLow; //< integral limit float dt; //< delta-time dt float angularLimit; //sets limit for how far Crazyflie can tip, to prevent flipping float angularLimitLow; //^ float thrustLimit; //Sets upper limit for Thrust Output (60000?) **? float thrustLimitLow; //Sets lower limit for thrust Output (10001) } PidObject; </pre> </code> </blockquote> :2. To simplify scaling up the code to multiple Crazyflies, we will create a <code> ControllerObject </code> that contains multiple PID structs as shown (code in ''controller.h''): <blockquote> <code> <pre> typedef struct { PidObject pidRoll; PidObject pidPitch; PidObject pidYaw; PidObject pidX; PidObject pidY; PidObject pidZ; bool isInit; } ControllerObject; </pre> </code> </blockquote> :3. Then we initialize the Objects to 0 at the start of each run (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> ControllerObject pidCtrl1 = { 0 }; // init all fields to zero ControllerObject pidCtrl2 = { 0 }; // init all fields to zero ControllerObject pidCtrl3 = { 0 }; // init all fields to zero ControllerObject pidCtrl4 = { 0 }; // init all fields to zero </pre> </code> </blockquote> :4. Then populate the PidObjects with the desired parameters (code in ''pid.c''): <blockquote> <code> <pre> void pidInit(PidObject* pid, const float desired, const float kp, const float ki, const float kd, const float dt) { pid->error = 0; pid->prevError = 0; pid->integ = 0; pid->deriv = 0; pid->desired = desired; pid->kp = kp; pid->ki = ki; pid->kd = kd; pid->iLimit = DEFAULT_PID_INTEGRATION_LIMIT; pid->iLimitLow = -DEFAULT_PID_INTEGRATION_LIMIT; pid->angularLimit = DEFAULT_PID_ANGLE_OUTPUT; pid->angularLimitLow = -DEFAULT_PID_ANGLE_OUTPUT; pid->thrustLimit = DEFAULT_PID_HIGH_THRUST_LIMIT; pid->thrustLimitLow = DEFAULT_PID_LOW_THRUST_LIMIT; pid->dt = dt; } </pre> </code> </blockquote> Using the above function for each of the <code>PidObjects</code> inside of the <code>ControllerObject</code> below (code in ''controller.c''): <blockquote> <code> <pre> void controllerInit( ControllerObject * ctrl ) { if(ctrl->isInit) return; pidInit(&ctrl->pidY, 0, PID_Y_KP, PID_Y_KI, PID_Y_KD, CAMERA_UPDATE_DT); //for Roll PID pidInit(&ctrl->pidX, 0, PID_X_KP, PID_X_KI, PID_X_KD, CAMERA_UPDATE_DT); //for Pitch PID pidInit(&ctrl->pidYaw, 0, PID_YAW_KP, PID_YAW_KI, PID_YAW_KD, CAMERA_UPDATE_DT); pidInit(&ctrl->pidZ, 0, PID_Z_KP, PID_Z_KI, PID_Z_KD, CAMERA_UPDATE_DT); pidSetIntegralLimit(&ctrl->pidY, PID_Y_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidX, PID_X_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidYaw, PID_YAW_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidZ, PID_Z_INTEGRATION_LIMIT); ctrl->isInit = true; } </pre> </code> </blockquote> '''Note:''' If we have multiple Crazyflies we need a <code>ControllerObject</code> for each Crazyflie (code in ''eris_vrpn.cpp'') <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl1 ); controllerInit( &pidCtrl1 ); #endif #if NUM_QUADS >= 2 controllerResetAllPID( &pidCtrl2 ); controllerInit( &pidCtrl2 ); #endif #if NUM_QUADS >=3 controllerResetAllPID( &pidCtrl3 ); controllerInit( &pidCtrl3 ); #endif #if NUM_QUADS >=4 controllerResetAllPID( &pidCtrl4 ); controllerInit( &pidCtrl4 ); #endif </pre> </code> </blockquote> Now the initialization of the Controllers is complete. ====Calculating the PID's==== :1. Each loop we want to calculate the PID output (code in ''pid.c''): <blockquote> <code> <pre> float pidUpdateAngle(PidObject* pid, const float measured, const bool updateError) //**USED FOR ATTITUDE CONTROL { float output; if(updateError) { pid->error = pid->desired - measured; //Calculates current error } pid->integ += pid->error * pid->dt; //Calculates integral term if(pid->integ > pid->iLimit) //Checks that the integral term stays below the integral limit (anti-windup) { pid->integ = pid->iLimit; } else if(pid->integ < pid->iLimitLow) { pid->integ = pid->iLimitLow; } pid->deriv = (pid->error - pid->prevError) / pid->dt; //Calculates derivative term pid->outP = pid->kp* pid->error; pid->outI = pid->ki * pid->integ; pid->outD = pid->kd * pid->deriv; output = pid->outP + pid->outI + pid->outD; //Adds up all 3 calculated terms for output if(output > pid->angularLimit) //Limits amount Crazyflie can tip { output = pid->angularLimit; } if(output < pid->angularLimitLow) //Limits amount Crazyflie can tip { output = pid->angularLimitLow; } pid->prevError = pid->error; //Stores the current error for next loop return output; } </pre> </code> </blockquote> '''Note:''' There are 3 different versions of this Function (for Angle, Thrust, and Yaw) since each has different output limits. :2. Using the function above, combine all PID calculations into one function (code in ''controller.c''): <blockquote> <code> <pre> void controllerCorrectAttitudePID(ControllerObject * ctrl, float xPositionActual, float yPositionActual, float zPositionActual, float eulerYawActual, float xPositionDesired, float yPositionDesired, float zPositionDesired, float eulerYawDesired, float* rollControlOutput, float* pitchControlOutput, float* yawControlOutput, float* thrustControlOutput) { pidSetDesired(&ctrl->pidX, xPositionDesired); *pitchControlOutput = pidUpdateAngle(&ctrl->pidX, xPositionActual, false); //Originally true pidSetDesired(&ctrl->pidY, yPositionDesired); *rollControlOutput = pidUpdateAngle(&ctrl->pidY, yPositionActual, false); //Originally true pidSetDesired(&ctrl->pidZ, zPositionDesired); *thrustControlOutput = pidUpdateThrust(&ctrl->pidZ,zPositionActual, true); float yawError; pidSetDesired(&ctrl->pidYaw, eulerYawDesired); yawError = eulerYawDesired - eulerYawActual; if(yawError > 180.0) //Ensures Yaw error stays between -180 and 180 degrees yawError -= 360.0; else if(yawError < -180.0) yawError += 360.0; pidSetError(&ctrl->pidYaw, yawError); *yawControlOutput = pidUpdateYaw(&ctrl->pidYaw, eulerYawActual, true); //originally false } </pre> </code> </blockquote> :3. In each Callback, calculate the Controller outputs, assigned to pointer values<code>*rollControlOutput</code>, <code>*pitchControlOutput</code>, etc... (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; //Calculates error externally controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); </pre> </code> </blockquote> '''Note:''' We calculate error externally for X and Y because certain swarm controllers need special setpoint modifiers (this way we can switch modes without effecting the default setpoint): '''Example:''' Follow Hand Mode Error (Crazyflie1 will have setpoint -0.5 m lower in X and +0.5 m higher in Y than your hand trackable): <blockquote> <code> <pre> ... xError1 = (xPositionHand - 0.5) - xPosition1; yError1 = (yPositionHand + 0.5) - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); ... </pre> </code> </blockquote> :4. Repeat for each set of new location data. ---- <center> '''Modifications Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> def5be89202f4e14a8c2ad3a915800c802309765 71 69 2016-07-13T18:11:21Z Jnoronha 3 added ellipses wikitext text/x-wiki The Crazyflie platform is completely customizable when it comes to the control design. As long as the controller can be written in C or C++, we can implement it in the Platform. This applies to both the controllers run on the PC Client and the controllers run on the Firmware of the Crazyflie. Originally the only controllers in the Platform were Firmware PID's that controlled the angular position and rates of the Crazyflie for hand flight. The original controller layout can be seen here [[#Original PID Controllers (Angular Rotation)|Original PID's]]. Below you will find documentation on the different types of Controllers that have been applied to the platform, organized by their location in the Platform. == Firmware == === Original PID Controllers (Angular Rotation) === Directly on the Crazyflie Firmware there are 5 PID controllers as seen here: [[Image:FirmwareOnlyPIDArchitecture.png|500px]] The Pitch and Roll angular position PID's receive constant setpoints from some outside source (gamepad controller or automated controller). The outputs of those angular position controllers is then fed into the angular rate controllers as shown. This final output is then fed into the Motor Command block which converts the angular rate setpoints into motor commands. ---- ===State Estimator=== ('''***NOT YET IMPLEMENTED***''') Bitcraze is currently working on adding a state estimator onto the Firmware to handle control calculations instead of the PID. The code is in place but the controller is not yet used as of '''7/13/16'''. == PC Client == === PID Controllers (Position and Yaw) === The first controller implemented on the Client were 4 PID controllers used to stabilize the Crazyflie's position in X, Y, and Z, and angular position in Yaw respectively. These PID's feed directly into the Firmware PID's as seen here: [[Image:CompletePIDArchitectureFigure.png|500px]] The controllers inside the red box are the original PID controllers located on the Firmware as shown above in the [[#Original PID Controllers (Angular Rotation)|Original PID's]]. ====Initialize the PID's==== :1. To start we create a struct with all the necessary variables (code from ''pid.h''): <blockquote> <code> <pre> typedef struct { float desired; //< set point float error; //< error float prevError; //< previous error float integ; //< integral float deriv; //< derivative float kp; //< proportional gain float ki; //< integral gain float kd; //< derivative gain float outP; //< proportional output (debugging) float outI; //< integral output (debugging) float outD; //< derivative output (debugging) float iLimit; //< integral limit float iLimitLow; //< integral limit float dt; //< delta-time dt float angularLimit; //sets limit for how far Crazyflie can tip, to prevent flipping float angularLimitLow; //^ float thrustLimit; //Sets upper limit for Thrust Output (60000?) **? float thrustLimitLow; //Sets lower limit for thrust Output (10001) } PidObject; </pre> </code> </blockquote> :2. To simplify scaling up the code to multiple Crazyflies, we will create a <code> ControllerObject </code> that contains multiple PID structs as shown (code in ''controller.h''): <blockquote> <code> <pre> typedef struct { PidObject pidRoll; PidObject pidPitch; PidObject pidYaw; PidObject pidX; PidObject pidY; PidObject pidZ; bool isInit; } ControllerObject; </pre> </code> </blockquote> :3. Then we initialize the Objects to 0 at the start of each run (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> ControllerObject pidCtrl1 = { 0 }; // init all fields to zero ControllerObject pidCtrl2 = { 0 }; // init all fields to zero ControllerObject pidCtrl3 = { 0 }; // init all fields to zero ControllerObject pidCtrl4 = { 0 }; // init all fields to zero </pre> </code> </blockquote> :4. Then populate the PidObjects with the desired parameters (code in ''pid.c''): <blockquote> <code> <pre> void pidInit(PidObject* pid, const float desired, const float kp, const float ki, const float kd, const float dt) { pid->error = 0; pid->prevError = 0; pid->integ = 0; pid->deriv = 0; pid->desired = desired; pid->kp = kp; pid->ki = ki; pid->kd = kd; pid->iLimit = DEFAULT_PID_INTEGRATION_LIMIT; pid->iLimitLow = -DEFAULT_PID_INTEGRATION_LIMIT; pid->angularLimit = DEFAULT_PID_ANGLE_OUTPUT; pid->angularLimitLow = -DEFAULT_PID_ANGLE_OUTPUT; pid->thrustLimit = DEFAULT_PID_HIGH_THRUST_LIMIT; pid->thrustLimitLow = DEFAULT_PID_LOW_THRUST_LIMIT; pid->dt = dt; } </pre> </code> </blockquote> Using the above function for each of the <code>PidObjects</code> inside of the <code>ControllerObject</code> below (code in ''controller.c''): <blockquote> <code> <pre> void controllerInit( ControllerObject * ctrl ) { if(ctrl->isInit) return; pidInit(&ctrl->pidY, 0, PID_Y_KP, PID_Y_KI, PID_Y_KD, CAMERA_UPDATE_DT); //for Roll PID pidInit(&ctrl->pidX, 0, PID_X_KP, PID_X_KI, PID_X_KD, CAMERA_UPDATE_DT); //for Pitch PID pidInit(&ctrl->pidYaw, 0, PID_YAW_KP, PID_YAW_KI, PID_YAW_KD, CAMERA_UPDATE_DT); pidInit(&ctrl->pidZ, 0, PID_Z_KP, PID_Z_KI, PID_Z_KD, CAMERA_UPDATE_DT); pidSetIntegralLimit(&ctrl->pidY, PID_Y_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidX, PID_X_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidYaw, PID_YAW_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidZ, PID_Z_INTEGRATION_LIMIT); ctrl->isInit = true; } </pre> </code> </blockquote> '''Note:''' If we have multiple Crazyflies we need a <code>ControllerObject</code> for each Crazyflie (code in ''eris_vrpn.cpp'') <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl1 ); controllerInit( &pidCtrl1 ); #endif #if NUM_QUADS >= 2 controllerResetAllPID( &pidCtrl2 ); controllerInit( &pidCtrl2 ); #endif #if NUM_QUADS >=3 controllerResetAllPID( &pidCtrl3 ); controllerInit( &pidCtrl3 ); #endif #if NUM_QUADS >=4 controllerResetAllPID( &pidCtrl4 ); controllerInit( &pidCtrl4 ); #endif </pre> </code> </blockquote> Now the initialization of the Controllers is complete. ====Calculating the PID's==== :1. Each loop we want to calculate the PID output (code in ''pid.c''): <blockquote> <code> <pre> float pidUpdateAngle(PidObject* pid, const float measured, const bool updateError) //**USED FOR ATTITUDE CONTROL { float output; if(updateError) { pid->error = pid->desired - measured; //Calculates current error } pid->integ += pid->error * pid->dt; //Calculates integral term if(pid->integ > pid->iLimit) //Checks that the integral term stays below the integral limit (anti-windup) { pid->integ = pid->iLimit; } else if(pid->integ < pid->iLimitLow) { pid->integ = pid->iLimitLow; } pid->deriv = (pid->error - pid->prevError) / pid->dt; //Calculates derivative term pid->outP = pid->kp* pid->error; pid->outI = pid->ki * pid->integ; pid->outD = pid->kd * pid->deriv; output = pid->outP + pid->outI + pid->outD; //Adds up all 3 calculated terms for output if(output > pid->angularLimit) //Limits amount Crazyflie can tip { output = pid->angularLimit; } if(output < pid->angularLimitLow) //Limits amount Crazyflie can tip { output = pid->angularLimitLow; } pid->prevError = pid->error; //Stores the current error for next loop return output; } </pre> </code> </blockquote> '''Note:''' There are 3 different versions of this Function (for Angle, Thrust, and Yaw) since each has different output limits. :2. Using the function above, combine all PID calculations into one function (code in ''controller.c''): <blockquote> <code> <pre> void controllerCorrectAttitudePID(ControllerObject * ctrl, float xPositionActual, float yPositionActual, float zPositionActual, float eulerYawActual, float xPositionDesired, float yPositionDesired, float zPositionDesired, float eulerYawDesired, float* rollControlOutput, float* pitchControlOutput, float* yawControlOutput, float* thrustControlOutput) { pidSetDesired(&ctrl->pidX, xPositionDesired); *pitchControlOutput = pidUpdateAngle(&ctrl->pidX, xPositionActual, false); //Originally true pidSetDesired(&ctrl->pidY, yPositionDesired); *rollControlOutput = pidUpdateAngle(&ctrl->pidY, yPositionActual, false); //Originally true pidSetDesired(&ctrl->pidZ, zPositionDesired); *thrustControlOutput = pidUpdateThrust(&ctrl->pidZ,zPositionActual, true); float yawError; pidSetDesired(&ctrl->pidYaw, eulerYawDesired); yawError = eulerYawDesired - eulerYawActual; if(yawError > 180.0) //Ensures Yaw error stays between -180 and 180 degrees yawError -= 360.0; else if(yawError < -180.0) yawError += 360.0; pidSetError(&ctrl->pidYaw, yawError); *yawControlOutput = pidUpdateYaw(&ctrl->pidYaw, eulerYawActual, true); //originally false } </pre> </code> </blockquote> :3. In each Callback, calculate the Controller outputs, assigned to pointer values<code>*rollControlOutput</code>, <code>*pitchControlOutput</code>, etc... (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; //Calculates error externally controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); </pre> </code> </blockquote> '''Note:''' We calculate error externally for X and Y because certain swarm controllers need special setpoint modifiers (this way we can switch modes without effecting the default setpoint): '''Example:''' Follow Hand Mode Error (Crazyflie1 will have setpoint -0.5 m lower in X and +0.5 m higher in Y than your hand trackable): <blockquote> <code> <pre> ... xError1 = (xPositionHand - 0.5) - xPosition1; yError1 = (yPositionHand + 0.5) - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); ... </pre> </code> </blockquote> :4. Repeat for each set of new location data... ---- <center> '''Modifications Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 8655e4c99f766f75f68dbe1d76872bbcc2cf8d77 72 71 2016-07-13T18:25:29Z Jnoronha 3 Added disclaimer to state estimator heading wikitext text/x-wiki The Crazyflie platform is completely customizable when it comes to the control design. As long as the controller can be written in C or C++, we can implement it in the Platform. This applies to both the controllers run on the PC Client and the controllers run on the Firmware of the Crazyflie. Originally the only controllers in the Platform were Firmware PID's that controlled the angular position and rates of the Crazyflie for hand flight. The original controller layout can be seen here [[#Original PID Controllers (Angular Rotation)|Original PID's]]. Below you will find documentation on the different types of Controllers that have been applied to the platform, organized by their location in the Platform. == Firmware == === Original PID Controllers (Angular Rotation) === Directly on the Crazyflie Firmware there are 5 PID controllers as seen here: [[Image:FirmwareOnlyPIDArchitecture.png|500px]] The Pitch and Roll angular position PID's receive constant setpoints from some outside source (gamepad controller or automated controller). The outputs of those angular position controllers is then fed into the angular rate controllers as shown. This final output is then fed into the Motor Command block which converts the angular rate setpoints into motor commands. ---- ===State Estimator (Not Implemented Yet)=== ('''***NOT YET IMPLEMENTED***''') Bitcraze is currently working on adding a state estimator onto the Firmware to handle control calculations instead of the PID. The code is in place but the controller is not yet used as of '''7/13/16'''. == PC Client == === PID Controllers (Position and Yaw) === The first controller implemented on the Client were 4 PID controllers used to stabilize the Crazyflie's position in X, Y, and Z, and angular position in Yaw respectively. These PID's feed directly into the Firmware PID's as seen here: [[Image:CompletePIDArchitectureFigure.png|500px]] The controllers inside the red box are the original PID controllers located on the Firmware as shown above in the [[#Original PID Controllers (Angular Rotation)|Original PID's]]. ====Initialize the PID's==== :1. To start we create a struct with all the necessary variables (code from ''pid.h''): <blockquote> <code> <pre> typedef struct { float desired; //< set point float error; //< error float prevError; //< previous error float integ; //< integral float deriv; //< derivative float kp; //< proportional gain float ki; //< integral gain float kd; //< derivative gain float outP; //< proportional output (debugging) float outI; //< integral output (debugging) float outD; //< derivative output (debugging) float iLimit; //< integral limit float iLimitLow; //< integral limit float dt; //< delta-time dt float angularLimit; //sets limit for how far Crazyflie can tip, to prevent flipping float angularLimitLow; //^ float thrustLimit; //Sets upper limit for Thrust Output (60000?) **? float thrustLimitLow; //Sets lower limit for thrust Output (10001) } PidObject; </pre> </code> </blockquote> :2. To simplify scaling up the code to multiple Crazyflies, we will create a <code> ControllerObject </code> that contains multiple PID structs as shown (code in ''controller.h''): <blockquote> <code> <pre> typedef struct { PidObject pidRoll; PidObject pidPitch; PidObject pidYaw; PidObject pidX; PidObject pidY; PidObject pidZ; bool isInit; } ControllerObject; </pre> </code> </blockquote> :3. Then we initialize the Objects to 0 at the start of each run (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> ControllerObject pidCtrl1 = { 0 }; // init all fields to zero ControllerObject pidCtrl2 = { 0 }; // init all fields to zero ControllerObject pidCtrl3 = { 0 }; // init all fields to zero ControllerObject pidCtrl4 = { 0 }; // init all fields to zero </pre> </code> </blockquote> :4. Then populate the PidObjects with the desired parameters (code in ''pid.c''): <blockquote> <code> <pre> void pidInit(PidObject* pid, const float desired, const float kp, const float ki, const float kd, const float dt) { pid->error = 0; pid->prevError = 0; pid->integ = 0; pid->deriv = 0; pid->desired = desired; pid->kp = kp; pid->ki = ki; pid->kd = kd; pid->iLimit = DEFAULT_PID_INTEGRATION_LIMIT; pid->iLimitLow = -DEFAULT_PID_INTEGRATION_LIMIT; pid->angularLimit = DEFAULT_PID_ANGLE_OUTPUT; pid->angularLimitLow = -DEFAULT_PID_ANGLE_OUTPUT; pid->thrustLimit = DEFAULT_PID_HIGH_THRUST_LIMIT; pid->thrustLimitLow = DEFAULT_PID_LOW_THRUST_LIMIT; pid->dt = dt; } </pre> </code> </blockquote> Using the above function for each of the <code>PidObjects</code> inside of the <code>ControllerObject</code> below (code in ''controller.c''): <blockquote> <code> <pre> void controllerInit( ControllerObject * ctrl ) { if(ctrl->isInit) return; pidInit(&ctrl->pidY, 0, PID_Y_KP, PID_Y_KI, PID_Y_KD, CAMERA_UPDATE_DT); //for Roll PID pidInit(&ctrl->pidX, 0, PID_X_KP, PID_X_KI, PID_X_KD, CAMERA_UPDATE_DT); //for Pitch PID pidInit(&ctrl->pidYaw, 0, PID_YAW_KP, PID_YAW_KI, PID_YAW_KD, CAMERA_UPDATE_DT); pidInit(&ctrl->pidZ, 0, PID_Z_KP, PID_Z_KI, PID_Z_KD, CAMERA_UPDATE_DT); pidSetIntegralLimit(&ctrl->pidY, PID_Y_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidX, PID_X_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidYaw, PID_YAW_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidZ, PID_Z_INTEGRATION_LIMIT); ctrl->isInit = true; } </pre> </code> </blockquote> '''Note:''' If we have multiple Crazyflies we need a <code>ControllerObject</code> for each Crazyflie (code in ''eris_vrpn.cpp'') <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl1 ); controllerInit( &pidCtrl1 ); #endif #if NUM_QUADS >= 2 controllerResetAllPID( &pidCtrl2 ); controllerInit( &pidCtrl2 ); #endif #if NUM_QUADS >=3 controllerResetAllPID( &pidCtrl3 ); controllerInit( &pidCtrl3 ); #endif #if NUM_QUADS >=4 controllerResetAllPID( &pidCtrl4 ); controllerInit( &pidCtrl4 ); #endif </pre> </code> </blockquote> Now the initialization of the Controllers is complete. ====Calculating the PID's==== :1. Each loop we want to calculate the PID output (code in ''pid.c''): <blockquote> <code> <pre> float pidUpdateAngle(PidObject* pid, const float measured, const bool updateError) //**USED FOR ATTITUDE CONTROL { float output; if(updateError) { pid->error = pid->desired - measured; //Calculates current error } pid->integ += pid->error * pid->dt; //Calculates integral term if(pid->integ > pid->iLimit) //Checks that the integral term stays below the integral limit (anti-windup) { pid->integ = pid->iLimit; } else if(pid->integ < pid->iLimitLow) { pid->integ = pid->iLimitLow; } pid->deriv = (pid->error - pid->prevError) / pid->dt; //Calculates derivative term pid->outP = pid->kp* pid->error; pid->outI = pid->ki * pid->integ; pid->outD = pid->kd * pid->deriv; output = pid->outP + pid->outI + pid->outD; //Adds up all 3 calculated terms for output if(output > pid->angularLimit) //Limits amount Crazyflie can tip { output = pid->angularLimit; } if(output < pid->angularLimitLow) //Limits amount Crazyflie can tip { output = pid->angularLimitLow; } pid->prevError = pid->error; //Stores the current error for next loop return output; } </pre> </code> </blockquote> '''Note:''' There are 3 different versions of this Function (for Angle, Thrust, and Yaw) since each has different output limits. :2. Using the function above, combine all PID calculations into one function (code in ''controller.c''): <blockquote> <code> <pre> void controllerCorrectAttitudePID(ControllerObject * ctrl, float xPositionActual, float yPositionActual, float zPositionActual, float eulerYawActual, float xPositionDesired, float yPositionDesired, float zPositionDesired, float eulerYawDesired, float* rollControlOutput, float* pitchControlOutput, float* yawControlOutput, float* thrustControlOutput) { pidSetDesired(&ctrl->pidX, xPositionDesired); *pitchControlOutput = pidUpdateAngle(&ctrl->pidX, xPositionActual, false); //Originally true pidSetDesired(&ctrl->pidY, yPositionDesired); *rollControlOutput = pidUpdateAngle(&ctrl->pidY, yPositionActual, false); //Originally true pidSetDesired(&ctrl->pidZ, zPositionDesired); *thrustControlOutput = pidUpdateThrust(&ctrl->pidZ,zPositionActual, true); float yawError; pidSetDesired(&ctrl->pidYaw, eulerYawDesired); yawError = eulerYawDesired - eulerYawActual; if(yawError > 180.0) //Ensures Yaw error stays between -180 and 180 degrees yawError -= 360.0; else if(yawError < -180.0) yawError += 360.0; pidSetError(&ctrl->pidYaw, yawError); *yawControlOutput = pidUpdateYaw(&ctrl->pidYaw, eulerYawActual, true); //originally false } </pre> </code> </blockquote> :3. In each Callback, calculate the Controller outputs, assigned to pointer values<code>*rollControlOutput</code>, <code>*pitchControlOutput</code>, etc... (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; //Calculates error externally controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); </pre> </code> </blockquote> '''Note:''' We calculate error externally for X and Y because certain swarm controllers need special setpoint modifiers (this way we can switch modes without effecting the default setpoint): '''Example:''' Follow Hand Mode Error (Crazyflie1 will have setpoint -0.5 m lower in X and +0.5 m higher in Y than your hand trackable): <blockquote> <code> <pre> ... xError1 = (xPositionHand - 0.5) - xPosition1; yError1 = (yPositionHand + 0.5) - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); ... </pre> </code> </blockquote> :4. Repeat for each set of new location data... ---- <center> '''Modifications Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> ce5017ac82c7e736b57aa24915c37e1fc2063831 Crazyflie Swarm 0 2 70 17 2016-07-13T18:08:43Z Jnoronha 3 Linked to radio channel change sub-section wikitext text/x-wiki The Crazyflie Swarm is a Networked Control platform designed for students to learn more about control and for researchers that wish to apply their research in practice. Platform development was started during the Summer of 2015 and continues to this day. Here you will find descriptions on how the platform works, how you can use it, and how you can get involved in developing the platform further! == Background == The Crazyflie Swarm platform is based off of the ''Crazyflie'' Nano-quadcopter produced and maintained by [https://www.bitcraze.io/ Bitcraze]. The ''Crazyflie'' is completely open-source so we are able to look at and modify any part of the code and customize it to our needs. === Major Platform Components: === [[Image: High_Level_Figure_(Single_Radio_Single_Crazyflie_NO_NUMBERS_CROPPED).jpg‎|thumb|right|A high level overview of the Crazyflie Platform]] *[[PC Client Software]] *[[Firmware]] *[[USB Radio]] == Modifying the Platform == *[[Controller]] *[[Logging]] *[[Keyboard Commands]] *[[USB Radio#Changing Radio Channel|Changing Radio Channel]] *[[Flight Modes]] *[[Callbacks]] *[[Adding a Crazyflie]] *[[:Firmware]] == Frequently Asked Questions == For help with common problems and troubleshooting please see the [[FAQ]]. == [https://wiki.bitcraze.io/ Bitcraze Wiki] == Bitcraze maintains their own wiki on the many Crazyflie systems. If you can't find what you are looking for here, chances are they will have something to help. e4eebec1bd740c1cc1b89406fef0d142d67b8185 73 70 2016-07-13T18:27:33Z Jnoronha 3 added reminder to finish PC Client section wikitext text/x-wiki The Crazyflie Swarm is a Networked Control platform designed for students to learn more about control and for researchers that wish to apply their research in practice. Platform development was started during the Summer of 2015 and continues to this day. Here you will find descriptions on how the platform works, how you can use it, and how you can get involved in developing the platform further! == Background == The Crazyflie Swarm platform is based off of the ''Crazyflie'' Nano-quadcopter produced and maintained by [https://www.bitcraze.io/ Bitcraze]. The ''Crazyflie'' is completely open-source so we are able to look at and modify any part of the code and customize it to our needs. === Major Platform Components: === [[Image: High_Level_Figure_(Single_Radio_Single_Crazyflie_NO_NUMBERS_CROPPED).jpg‎|thumb|right|A high level overview of the Crazyflie Platform]] *[[PC Client Software]] '''(***TODO***)''' *[[Firmware]] *[[USB Radio]] == Modifying the Platform == *[[Controller]] *[[Logging]] *[[Keyboard Commands]] *[[USB Radio#Changing Radio Channel|Changing Radio Channel]] *[[Flight Modes]] *[[Callbacks]] *[[Adding a Crazyflie]] *[[:Firmware]] == Frequently Asked Questions == For help with common problems and troubleshooting please see the [[FAQ]]. == [https://wiki.bitcraze.io/ Bitcraze Wiki] == Bitcraze maintains their own wiki on the many Crazyflie systems. If you can't find what you are looking for here, chances are they will have something to help. dc1e9fabec8902b9f8cc8c67fcc29ec92f5b13f7 97 73 2016-07-19T18:56:18Z Jnoronha 3 Removed TODO from client wikitext text/x-wiki The Crazyflie Swarm is a Networked Control platform designed for students to learn more about control and for researchers that wish to apply their research in practice. Platform development was started during the Summer of 2015 and continues to this day. Here you will find descriptions on how the platform works, how you can use it, and how you can get involved in developing the platform further! == Background == The Crazyflie Swarm platform is based off of the ''Crazyflie'' Nano-quadcopter produced and maintained by [https://www.bitcraze.io/ Bitcraze]. The ''Crazyflie'' is completely open-source so we are able to look at and modify any part of the code and customize it to our needs. === Major Platform Components: === [[Image: High_Level_Figure_(Single_Radio_Single_Crazyflie_NO_NUMBERS_CROPPED).jpg‎|thumb|right|A high level overview of the Crazyflie Platform]] *[[PC Client Software]] *[[Firmware]] *[[USB Radio]] == Modifying the Platform == *[[Controller]] *[[Logging]] *[[Keyboard Commands]] *[[USB Radio#Changing Radio Channel|Changing Radio Channel]] *[[Flight Modes]] *[[Callbacks]] *[[Adding a Crazyflie]] *[[:Firmware]] == Frequently Asked Questions == For help with common problems and troubleshooting please see the [[FAQ]]. == [https://wiki.bitcraze.io/ Bitcraze Wiki] == Bitcraze maintains their own wiki on the many Crazyflie systems. If you can't find what you are looking for here, chances are they will have something to help. e4eebec1bd740c1cc1b89406fef0d142d67b8185 File:DefaultCrazyflieGUIBootloader.JPG 6 23 74 47 2016-07-18T19:57:28Z Jnoronha 3 uploaded a new version of "[[Image:DefaultCrazyflieGUIBootloader.JPG]]" wikitext text/x-wiki Screenshot of the Crazyflie Bootloader User Interface. 9414da3f61ffe8574ac5f9b79654f2f8294c89b3 File:DefaultCrazyflieGUIConnectScreen.JPG 6 27 75 2016-07-18T19:58:42Z Jnoronha 3 Screenshot of the Crazyflie GUI connect to radio window. wikitext text/x-wiki Screenshot of the Crazyflie GUI connect to radio window. 4c03f28f200c96bb4f336f5e667304c98f3b4037 File:DefaultCrazyflieGUILoggerScreen.JPG 6 28 76 2016-07-18T20:00:03Z Jnoronha 3 Screenshot of the Crazyflie GUI logging output wikitext text/x-wiki Screenshot of the Crazyflie GUI logging output 8fb3c169c5958e65b424b65fa95db06f05872b2e File:DefaultCrazyflieGUIParametersScreen.JPG 6 29 77 2016-07-18T20:00:55Z Jnoronha 3 Screenshot of the Crazyflie GUI Parameters Tab wikitext text/x-wiki Screenshot of the Crazyflie GUI Parameters Tab ef7255336a61589fd230dbc1017eae357b6ae0be File:CrazyflieLocationLayout.JPG 6 30 78 2016-07-18T20:02:10Z Jnoronha 3 Photo of the Default locations of the Current 4 Crazyflies is laid out. wikitext text/x-wiki Photo of the Default locations of the Current 4 Crazyflies is laid out. d83b1de3cf06308f7fc268bde4ce5e929f30d497 File:CrazyflieTerminalInitial.png 6 31 86 2016-07-19T17:42:18Z Jnoronha 3 Crazyflie Terminal showing the make command wikitext text/x-wiki Crazyflie Terminal showing the make command c6f990d31f07dfcf8d93d9f828ea053eeb121328 File:CrazyflieTerminalPostMake.png 6 32 87 2016-07-19T17:42:39Z Jnoronha 3 Crazyflie Terminal showing an error free make build wikitext text/x-wiki Crazyflie Terminal showing an error free make build d6cea0bf6c7a21708537aa1d95eead63570705c8 File:3CrazyflieTerminalRunProgram.png 6 33 88 2016-07-19T17:42:57Z Jnoronha 3 Crazyflie Terminal showing the run .exe command wikitext text/x-wiki Crazyflie Terminal showing the run .exe command 9d78db40abd506e403e8e7da4dae4fc9c9fdf42a File:CrazyflieTerminalRunProgram.png 6 34 89 2016-07-19T17:43:25Z Jnoronha 3 Crazyflie Terminal showing the run .exe command wikitext text/x-wiki Crazyflie Terminal showing the run .exe command 9d78db40abd506e403e8e7da4dae4fc9c9fdf42a File:CrazyflieTerminalProgramStarted.png 6 35 90 2016-07-19T17:43:54Z Jnoronha 3 Crazyflie Terminal showing Swarm Client ready for keyboard input wikitext text/x-wiki Crazyflie Terminal showing Swarm Client ready for keyboard input 17a5d428fc8c01f3bab6f28028b083544f9dcd8d File:CrazyflieTerminalKeyboardInput.png 6 36 91 2016-07-19T17:44:25Z Jnoronha 3 Crazyflie Terminal showing Swarm Client after keyboard input has been pressed wikitext text/x-wiki Crazyflie Terminal showing Swarm Client after keyboard input has been pressed b1a82197fcc216cdc42515cc3ec6fff3bda23b0d File:CrazyflieTerminalNoRadio.png 6 37 92 2016-07-19T17:44:54Z Jnoronha 3 Crazyflie Terminal showing Error Garbage if no Radio plugged in. wikitext text/x-wiki Crazyflie Terminal showing Error Garbage if no Radio plugged in. b33575b3a31b2001e05e2cd3f58ccb1118990e3b File:CrazyflieTerminalRadioDriverNotDeleted.png 6 38 93 2016-07-19T17:45:25Z Jnoronha 3 Crazyflie Terminal showing Error if Radio Driver was not properly deleted. (Unplug and Re-plug Radio Dongle) wikitext text/x-wiki Crazyflie Terminal showing Error if Radio Driver was not properly deleted. (Unplug and Re-plug Radio Dongle) d0b2014bc578e0e9c5b8c64f7855eaf84ab407a5 Logging 0 39 98 2016-07-19T19:23:12Z Jnoronha 3 Made intro and started init wikitext text/x-wiki The logging system is the most important analysis tool we have. This allows us to export any variable data we want out to an external text file. This way we can use any data processor to parse the data. (Excel, MATLAB, R, etc.) ==Initializing the Log Files== We first need to initialize the log files and prepare them before each test. :1. Create empty File Pointers 1c53d5e50c2bb45591030bf53d85899a7062d081 99 98 2016-07-19T19:56:18Z Jnoronha 3 Added Using the log file code wikitext text/x-wiki The logging system is the most important analysis tool we have. This allows us to export any variable data we want out to an external text file. This way we can use any data processor to parse the data. (Excel, MATLAB, R, etc.) ==Creating and Using the Log Files== We first need to initialize the log files and prepare them before each test. :1. Create empty File Pointers (code in 'eris_vrpn.cpp') <blockquote> <code> <pre> FILE * outHand = NULL; FILE * out1 = NULL; FILE * out2 = NULL; FILE * out3 = NULL; FILE * out4 = NULL; </pre> </code> </blockquote> :2. Make sure Logging is Enabled (and Basic Logging if desired) <blockquote> <code> <pre> #define USE_VRPN 1 #define USE_KEYBOARD 1 #define USE_PRINTOUT 0 #define USE_LOGGING 1 <---//Enables Full Logging #define USE_BASIC_LOGGING 1 <---//Only logs the necessities (FULL LOGGING MUST BE ENABLED FOR THIS TO WORK) #define USE_PR_YAW_CORRECT 0 #define USE_HAND 1 </pre> </code> </blockquote> :3. Create Log File Header (# = Log File Title, % = List of Variable Names, & = List of Variable Units) ::'''Note 1:''' This example is using BASIC_LOGGING 1, ::'''Note 2:''' Variables and units are separated by a double tab '\t\t' (Does not have to be '\t\t' any delimiter works) <blockquote> <code> <pre> const char * logHeaderHand = "#Hand Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tLoopTime\t\tLoopTimeDelta\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tseconds\t\tseconds\n"; const char * logHeader1 = "#Crazyflie1 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\t\tRadioRSSI\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\t\tstrength\n"; const char * logHeader2 = "#Crazyflie2 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader3 = "#Crazyflie3 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader4 = "#Crazyflie4 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; </pre> </code> </blockquote> :4. Open External .txt file and Print Header into file <blockquote> <code> <pre> #if USE_HAND outHand = fopen("hand.txt", "w"); //Opens text file with write permission if(outHand == NULL) { printf("Could not open hand.log: errno %d\n", errno); exit(-1); } fprintf(outHand, "%s\n", logHeaderHand); //Prints log header into corresponding file #endif if(cflieCopter1) //Checks to see if cflieCopter pointer has been initialized before opening file { out1 = fopen("cflie1.txt", "w"); if(out1 == NULL) { printf("Could not open cflie1.log: errno %d\n", errno); exit(-1); } fprintf(out1, "%s\n", logHeader1); } if(cflieCopter2) { out2 = fopen("cflie2.txt", "w"); if(out2 == NULL) { printf("Could not open cflie2.log:errno %d\n", errno); exit(-1); } fprintf(out2, "%s\n", logHeader2); } if(cflieCopter3) { out3 = fopen("cflie3.txt", "w"); if(out3 == NULL) { printf("Could not open cflie3.log:errno %d\n", errno); exit(-1); } fprintf(out3, "%s\n", logHeader3); } if(cflieCopter4) { out4 = fopen("cflie4.txt", "w"); if(out4 == NULL) { printf("Could not open cflie4.log:errno %d\n", errno); exit(-1); } fprintf(out4, "%s\n", logHeader4); } </pre> </code> </blockquote> :5. Init has Completed (Start Program Loop)... ::'''Note 1:''' This code is run at the end of the Callback for each Crazyflie initialized (Executes once per new data packet) ::'''Note 2:''' This example is using BASIC_LOGGING, and is only showing Crazyflie1's code. <blockquote> <code> <pre> fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); fprintf(out1, "\n"); </pre> </code> </blockquote> :6. Close External .txt files before ending program <blockquote> <code> <pre> #if USE_LOGGING #if USE_HAND fclose(outHand); #endif #if NUM_QUADS >= 1 fclose(out1); #endif #if NUM_QUADS >= 2 fclose(out2); #endif #if NUM_QUADS >= 3 fclose(out3); #endif #if NUM_QUADS >= 4 fclose(out4); #endif #endif </pre> </code> </blockquote> ---- <center> '''Modifications Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 224ea4d9249e07642abed4628324c84513312f75 100 99 2016-07-19T19:57:14Z Jnoronha 3 started matlab section wikitext text/x-wiki The logging system is the most important analysis tool we have. This allows us to export any variable data we want out to an external text file. This way we can use any data processor to parse the data. (Excel, MATLAB, R, etc.) ==Creating and Using the Log Files== We first need to initialize the log files and prepare them before each test. :1. Create empty File Pointers (code in 'eris_vrpn.cpp') <blockquote> <code> <pre> FILE * outHand = NULL; FILE * out1 = NULL; FILE * out2 = NULL; FILE * out3 = NULL; FILE * out4 = NULL; </pre> </code> </blockquote> :2. Make sure Logging is Enabled (and Basic Logging if desired) <blockquote> <code> <pre> #define USE_VRPN 1 #define USE_KEYBOARD 1 #define USE_PRINTOUT 0 #define USE_LOGGING 1 <---//Enables Full Logging #define USE_BASIC_LOGGING 1 <---//Only logs the necessities (FULL LOGGING MUST BE ENABLED FOR THIS TO WORK) #define USE_PR_YAW_CORRECT 0 #define USE_HAND 1 </pre> </code> </blockquote> :3. Create Log File Header (# = Log File Title, % = List of Variable Names, & = List of Variable Units) ::'''Note 1:''' This example is using BASIC_LOGGING 1, ::'''Note 2:''' Variables and units are separated by a double tab '\t\t' (Does not have to be '\t\t' any delimiter works) <blockquote> <code> <pre> const char * logHeaderHand = "#Hand Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tLoopTime\t\tLoopTimeDelta\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tseconds\t\tseconds\n"; const char * logHeader1 = "#Crazyflie1 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\t\tRadioRSSI\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\t\tstrength\n"; const char * logHeader2 = "#Crazyflie2 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader3 = "#Crazyflie3 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader4 = "#Crazyflie4 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; </pre> </code> </blockquote> :4. Open External .txt file and Print Header into file <blockquote> <code> <pre> #if USE_HAND outHand = fopen("hand.txt", "w"); //Opens text file with write permission if(outHand == NULL) { printf("Could not open hand.log: errno %d\n", errno); exit(-1); } fprintf(outHand, "%s\n", logHeaderHand); //Prints log header into corresponding file #endif if(cflieCopter1) //Checks to see if cflieCopter pointer has been initialized before opening file { out1 = fopen("cflie1.txt", "w"); if(out1 == NULL) { printf("Could not open cflie1.log: errno %d\n", errno); exit(-1); } fprintf(out1, "%s\n", logHeader1); } if(cflieCopter2) { out2 = fopen("cflie2.txt", "w"); if(out2 == NULL) { printf("Could not open cflie2.log:errno %d\n", errno); exit(-1); } fprintf(out2, "%s\n", logHeader2); } if(cflieCopter3) { out3 = fopen("cflie3.txt", "w"); if(out3 == NULL) { printf("Could not open cflie3.log:errno %d\n", errno); exit(-1); } fprintf(out3, "%s\n", logHeader3); } if(cflieCopter4) { out4 = fopen("cflie4.txt", "w"); if(out4 == NULL) { printf("Could not open cflie4.log:errno %d\n", errno); exit(-1); } fprintf(out4, "%s\n", logHeader4); } </pre> </code> </blockquote> :5. Init has Completed (Start Program Loop)... ::'''Note 1:''' This code is run at the end of the Callback for each Crazyflie initialized (Executes once per new data packet) ::'''Note 2:''' This example is using BASIC_LOGGING, and is only showing Crazyflie1's code. <blockquote> <code> <pre> fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); fprintf(out1, "\n"); </pre> </code> </blockquote> :6. Close External .txt files before ending program <blockquote> <code> <pre> #if USE_LOGGING #if USE_HAND fclose(outHand); #endif #if NUM_QUADS >= 1 fclose(out1); #endif #if NUM_QUADS >= 2 fclose(out2); #endif #if NUM_QUADS >= 3 fclose(out3); #endif #if NUM_QUADS >= 4 fclose(out4); #endif #endif </pre> </code> </blockquote> ==MATLAB Parser== We use a Matlab script to parse the log files. ---- <center> '''Modifications Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> ca1550eb2539f2dcc779562e101a8d7b2d374cfd Logging 0 39 101 100 2016-07-19T20:28:09Z Jnoronha 3 wikitext text/x-wiki The logging system is the most important analysis tool we have. This allows us to export any variable data we want out to an external text file. This way we can use any data processor to parse the data. (Excel, MATLAB, R, etc.) ==Creating and Using the Log Files== We first need to initialize the log files and prepare them before each test. :1. Create empty File Pointers (code in 'eris_vrpn.cpp') <blockquote> <code> <pre> FILE * outHand = NULL; FILE * out1 = NULL; FILE * out2 = NULL; FILE * out3 = NULL; FILE * out4 = NULL; </pre> </code> </blockquote> :2. Make sure Logging is Enabled (and Basic Logging if desired) <blockquote> <code> <pre> #define USE_VRPN 1 #define USE_KEYBOARD 1 #define USE_PRINTOUT 0 #define USE_LOGGING 1 <---//Enables Full Logging #define USE_BASIC_LOGGING 1 <---//Only logs the necessities (FULL LOGGING MUST BE ENABLED FOR THIS TO WORK) #define USE_PR_YAW_CORRECT 0 #define USE_HAND 1 </pre> </code> </blockquote> :3. Create Log File Header (# = Log File Title, % = List of Variable Names, & = List of Variable Units) ::'''Note 1:''' This example is using BASIC_LOGGING 1, ::'''Note 2:''' Variables and units are separated by a double tab '\t\t' (Does not have to be '\t\t' any delimiter works) <blockquote> <code> <pre> const char * logHeaderHand = "#Hand Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tLoopTime\t\tLoopTimeDelta\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tseconds\t\tseconds\n"; const char * logHeader1 = "#Crazyflie1 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\t\tRadioRSSI\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\t\tstrength\n"; const char * logHeader2 = "#Crazyflie2 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader3 = "#Crazyflie3 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader4 = "#Crazyflie4 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; </pre> </code> </blockquote> :4. Open External .txt file and Print Header into file <blockquote> <code> <pre> #if USE_HAND outHand = fopen("hand.txt", "w"); //Opens text file with write permission if(outHand == NULL) { printf("Could not open hand.log: errno %d\n", errno); exit(-1); } fprintf(outHand, "%s\n", logHeaderHand); //Prints log header into corresponding file #endif if(cflieCopter1) //Checks to see if cflieCopter pointer has been initialized before opening file { out1 = fopen("cflie1.txt", "w"); if(out1 == NULL) { printf("Could not open cflie1.log: errno %d\n", errno); exit(-1); } fprintf(out1, "%s\n", logHeader1); } if(cflieCopter2) { out2 = fopen("cflie2.txt", "w"); if(out2 == NULL) { printf("Could not open cflie2.log:errno %d\n", errno); exit(-1); } fprintf(out2, "%s\n", logHeader2); } if(cflieCopter3) { out3 = fopen("cflie3.txt", "w"); if(out3 == NULL) { printf("Could not open cflie3.log:errno %d\n", errno); exit(-1); } fprintf(out3, "%s\n", logHeader3); } if(cflieCopter4) { out4 = fopen("cflie4.txt", "w"); if(out4 == NULL) { printf("Could not open cflie4.log:errno %d\n", errno); exit(-1); } fprintf(out4, "%s\n", logHeader4); } </pre> </code> </blockquote> :5. Init has Completed (Start Program Loop) Prints Variable values to file... ::'''Note 1:''' This code is run at the end of the Callback for each Crazyflie initialized (Executes once per new data packet) ::'''Note 2:''' This example is using BASIC_LOGGING, and is only showing Crazyflie1's code. <blockquote> <code> <pre> fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); fprintf(out1, "\n"); </pre> </code> </blockquote> :6. Close External .txt files before ending program <blockquote> <code> <pre> #if USE_LOGGING #if USE_HAND fclose(outHand); #endif #if NUM_QUADS >= 1 fclose(out1); #endif #if NUM_QUADS >= 2 fclose(out2); #endif #if NUM_QUADS >= 3 fclose(out3); #endif #if NUM_QUADS >= 4 fclose(out4); #endif #endif </pre> </code> </blockquote> ==MATLAB Parser== We use a Matlab script to parse the log files. ---- <center> '''Modifications Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 0afffe5819ef804c90f4eb5ba98a013f62828f45 103 101 2016-07-20T16:42:58Z Jnoronha 3 Finished using logging in client wikitext text/x-wiki The logging system is the most important analysis tool we have. This allows us to export any variable data we want out to an external text file. This way we can use any data processor to parse the data. (Excel, MATLAB, R, etc.) ==Creating and Using the Log Files== We first need to initialize the log files and prepare them before each test. :1. Create empty File Pointers (code in 'eris_vrpn.cpp') <blockquote> <code> <pre> FILE * outHand = NULL; FILE * out1 = NULL; FILE * out2 = NULL; FILE * out3 = NULL; FILE * out4 = NULL; </pre> </code> </blockquote> :2. Make sure Logging is Enabled (and Basic Logging if desired) <blockquote> <code> <pre> #define USE_VRPN 1 #define USE_KEYBOARD 1 #define USE_PRINTOUT 0 #define USE_LOGGING 1 <---//Enables Full Logging #define USE_BASIC_LOGGING 1 <---//Only logs the necessities (FULL LOGGING MUST BE ENABLED FOR THIS TO WORK) #define USE_PR_YAW_CORRECT 0 #define USE_HAND 1 </pre> </code> </blockquote> :3. Create Log File Header (# = Log File Title, % = List of Variable Names, & = List of Variable Units) ::'''Note 1:''' This example is using BASIC_LOGGING 1, ::'''Note 2:''' Variables and units are separated by a double tab '\t\t' (Does not have to be '\t\t' any delimiter works) <blockquote> <code> <pre> const char * logHeaderHand = "#Hand Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tLoopTime\t\tLoopTimeDelta\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tseconds\t\tseconds\n"; const char * logHeader1 = "#Crazyflie1 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\t\tRadioRSSI\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\t\tstrength\n"; const char * logHeader2 = "#Crazyflie2 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader3 = "#Crazyflie3 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader4 = "#Crazyflie4 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; </pre> </code> </blockquote> :4. Open External .txt file and Print Header into file <blockquote> <code> <pre> #if USE_HAND outHand = fopen("hand.txt", "w"); //Opens text file with write permission if(outHand == NULL) { printf("Could not open hand.log: errno %d\n", errno); exit(-1); } fprintf(outHand, "%s\n", logHeaderHand); //Prints log header into corresponding file #endif if(cflieCopter1) //Checks to see if cflieCopter pointer has been initialized before opening file { out1 = fopen("cflie1.txt", "w"); if(out1 == NULL) { printf("Could not open cflie1.log: errno %d\n", errno); exit(-1); } fprintf(out1, "%s\n", logHeader1); } if(cflieCopter2) { out2 = fopen("cflie2.txt", "w"); if(out2 == NULL) { printf("Could not open cflie2.log:errno %d\n", errno); exit(-1); } fprintf(out2, "%s\n", logHeader2); } if(cflieCopter3) { out3 = fopen("cflie3.txt", "w"); if(out3 == NULL) { printf("Could not open cflie3.log:errno %d\n", errno); exit(-1); } fprintf(out3, "%s\n", logHeader3); } if(cflieCopter4) { out4 = fopen("cflie4.txt", "w"); if(out4 == NULL) { printf("Could not open cflie4.log:errno %d\n", errno); exit(-1); } fprintf(out4, "%s\n", logHeader4); } </pre> </code> </blockquote> :5. Init has Completed (Start Program Loop) Prints Variable values to file... ::'''Note 1:''' This code is run at the end of the Callback for each Crazyflie initialized (Executes once per new data packet) ::'''Note 2:''' This example is using BASIC_LOGGING, and is only showing Crazyflie1's code. <blockquote> <code> <pre> fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); fprintf(out1, "\n"); </pre> </code> </blockquote> :6. Close External .txt files before ending program <blockquote> <code> <pre> #if USE_LOGGING #if USE_HAND fclose(outHand); #endif #if NUM_QUADS >= 1 fclose(out1); #endif #if NUM_QUADS >= 2 fclose(out2); #endif #if NUM_QUADS >= 3 fclose(out3); #endif #if NUM_QUADS >= 4 fclose(out4); #endif #endif </pre> </code> </blockquote> ==MATLAB Parser== We use a Matlab script to parse the log files. ==Starting New Log Blocks== In the Swarm Client there is a sub-system designed for creating and maintaining Log Blocks. Once you have [[:Firmware#Log Blocks|created a new log block in the Firmware]] that you want to utilize we can do the following: :1. Create an Enable function for the New Log Block (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::enableMagnetometerLogging() { m_tocLogs->registerLoggingBlock("magnetometer", 1000); m_tocLogs->startLogging("mag.x", "magnetometer"); m_tocLogs->startLogging("mag.y", "magnetometer"); m_tocLogs->startLogging("mag.z", "magnetometer"); } </pre> </code> </blockquote> ::This will then register a log block called ''magnetometer'' on the Client, which will be updated every 1000 &mus. It will then update the values listed in the block (X, Y, Z of the magnetometer). ::'''Note 1:''' The ''"mag.x"'' term must match the name defined in the Firmware log block (see [[:Firmware#Log Blocks|firmware example 1]]) ::'''Note 2:''' The 2nd input to the ''startLogging'' function needs to match the name of the Client Log block we registered (in this case ''"magnetometer"'') :2. Add the ''enableLogBlock'' function we just made to the list of Log blocks we want at startup (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::startLogging() { // Register the desired sensor readings this->enableStabilizerLogging(); // this->enableGyroscopeLogging(); // this->enableAccelerometerLogging(); this->enableBatteryLogging(); this->enableMagnetometerLogging(); <-----//This is the one we just made // this->enableAltimeterLogging(); // this->enablePIDOutputLogging(); // this->enableRadioRSSILogging(); // this->enableMotorLogging(); return true; } </pre> </code> </blockquote> ::This ''startLogging'' function runs during Crazyflie startup and will start all the log blocks listed. As you can see we have some log blocks commented out currently so that we do NOT start those blocks. :3. Create Functions to Read the variable values during runtime (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> float CCrazyflie::magX() { return this->sensorDoubleValue("mag.x"); } float CCrazyflie::magY() { return this->sensorDoubleValue("mag.y"); } float CCrazyflie::magZ() { return this->sensorDoubleValue("mag.z"); } </pre> </code> </blockquote> ::So now we can use these sensor values, from the Firmware, in the Client code with <code>magX1 = cflieCopter1->magX()</code>. This will store the sensor value in the Client-side variable ''magX1''. :4. (OPTIONAL) We can also create a function to stop logging an individual log block in the Client (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::disableMagnetometerLogging() { m_tocLogs->unregisterLoggingBlock("magnetometer"); } </pre> </code> </blockquote> ::This is straightforward, it just tells the client to stop logging this block. :5. (OPTIONAL) And we can stop ALL log blocks in the client as well (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::stopLogging() { this->disableStabilizerLogging(); this->disableGyroscopeLogging(); this->disableAccelerometerLogging(); this->disableBatteryLogging(); // this->disableMagnetometerLogging(); // this->disableAltimeterLogging(); // this->disablePIDOutputLogging(); this->disableRadioRSSILogging(); this->disableMotorLogging(); return true; } </pre> </code> </blockquote> ---- <center> '''Modifications Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 89ae9aa3b9ca4e268ea81ba481012c8779b59365 105 103 2016-07-20T16:47:36Z Jnoronha 3 /* Starting New Log Blocks */ changed heading name wikitext text/x-wiki The logging system is the most important analysis tool we have. This allows us to export any variable data we want out to an external text file. This way we can use any data processor to parse the data. (Excel, MATLAB, R, etc.) ==Creating and Using the Log Files== We first need to initialize the log files and prepare them before each test. :1. Create empty File Pointers (code in 'eris_vrpn.cpp') <blockquote> <code> <pre> FILE * outHand = NULL; FILE * out1 = NULL; FILE * out2 = NULL; FILE * out3 = NULL; FILE * out4 = NULL; </pre> </code> </blockquote> :2. Make sure Logging is Enabled (and Basic Logging if desired) <blockquote> <code> <pre> #define USE_VRPN 1 #define USE_KEYBOARD 1 #define USE_PRINTOUT 0 #define USE_LOGGING 1 <---//Enables Full Logging #define USE_BASIC_LOGGING 1 <---//Only logs the necessities (FULL LOGGING MUST BE ENABLED FOR THIS TO WORK) #define USE_PR_YAW_CORRECT 0 #define USE_HAND 1 </pre> </code> </blockquote> :3. Create Log File Header (# = Log File Title, % = List of Variable Names, & = List of Variable Units) ::'''Note 1:''' This example is using BASIC_LOGGING 1, ::'''Note 2:''' Variables and units are separated by a double tab '\t\t' (Does not have to be '\t\t' any delimiter works) <blockquote> <code> <pre> const char * logHeaderHand = "#Hand Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tLoopTime\t\tLoopTimeDelta\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tseconds\t\tseconds\n"; const char * logHeader1 = "#Crazyflie1 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\t\tRadioRSSI\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\t\tstrength\n"; const char * logHeader2 = "#Crazyflie2 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader3 = "#Crazyflie3 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader4 = "#Crazyflie4 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; </pre> </code> </blockquote> :4. Open External .txt file and Print Header into file <blockquote> <code> <pre> #if USE_HAND outHand = fopen("hand.txt", "w"); //Opens text file with write permission if(outHand == NULL) { printf("Could not open hand.log: errno %d\n", errno); exit(-1); } fprintf(outHand, "%s\n", logHeaderHand); //Prints log header into corresponding file #endif if(cflieCopter1) //Checks to see if cflieCopter pointer has been initialized before opening file { out1 = fopen("cflie1.txt", "w"); if(out1 == NULL) { printf("Could not open cflie1.log: errno %d\n", errno); exit(-1); } fprintf(out1, "%s\n", logHeader1); } if(cflieCopter2) { out2 = fopen("cflie2.txt", "w"); if(out2 == NULL) { printf("Could not open cflie2.log:errno %d\n", errno); exit(-1); } fprintf(out2, "%s\n", logHeader2); } if(cflieCopter3) { out3 = fopen("cflie3.txt", "w"); if(out3 == NULL) { printf("Could not open cflie3.log:errno %d\n", errno); exit(-1); } fprintf(out3, "%s\n", logHeader3); } if(cflieCopter4) { out4 = fopen("cflie4.txt", "w"); if(out4 == NULL) { printf("Could not open cflie4.log:errno %d\n", errno); exit(-1); } fprintf(out4, "%s\n", logHeader4); } </pre> </code> </blockquote> :5. Init has Completed (Start Program Loop) Prints Variable values to file... ::'''Note 1:''' This code is run at the end of the Callback for each Crazyflie initialized (Executes once per new data packet) ::'''Note 2:''' This example is using BASIC_LOGGING, and is only showing Crazyflie1's code. <blockquote> <code> <pre> fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); fprintf(out1, "\n"); </pre> </code> </blockquote> :6. Close External .txt files before ending program <blockquote> <code> <pre> #if USE_LOGGING #if USE_HAND fclose(outHand); #endif #if NUM_QUADS >= 1 fclose(out1); #endif #if NUM_QUADS >= 2 fclose(out2); #endif #if NUM_QUADS >= 3 fclose(out3); #endif #if NUM_QUADS >= 4 fclose(out4); #endif #endif </pre> </code> </blockquote> ==MATLAB Parser== We use a Matlab script to parse the log files. ==New Client Log Blocks== In the Swarm Client there is a sub-system designed for creating and maintaining Log Blocks. Once you have [[:Firmware#Log Blocks|created a new log block in the Firmware]] that you want to utilize we can do the following: :1. Create an Enable function for the New Log Block (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::enableMagnetometerLogging() { m_tocLogs->registerLoggingBlock("magnetometer", 1000); m_tocLogs->startLogging("mag.x", "magnetometer"); m_tocLogs->startLogging("mag.y", "magnetometer"); m_tocLogs->startLogging("mag.z", "magnetometer"); } </pre> </code> </blockquote> ::This will then register a log block called ''magnetometer'' on the Client, which will be updated every 1000 &mu;s. It will then update the values listed in the block (X, Y, Z of the magnetometer). ::'''Note 1:''' The ''"mag.x"'' term must match the name defined in the Firmware log block (see [[:Firmware#Log Blocks|firmware example 1]]) ::'''Note 2:''' The 2nd input to the ''startLogging'' function needs to match the name of the Client Log block we registered (in this case ''"magnetometer"'') :2. Add the ''enableLogBlock'' function we just made to the list of Log blocks we want at startup (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::startLogging() { // Register the desired sensor readings this->enableStabilizerLogging(); // this->enableGyroscopeLogging(); // this->enableAccelerometerLogging(); this->enableBatteryLogging(); this->enableMagnetometerLogging(); <-----//This is the one we just made // this->enableAltimeterLogging(); // this->enablePIDOutputLogging(); // this->enableRadioRSSILogging(); // this->enableMotorLogging(); return true; } </pre> </code> </blockquote> ::This ''startLogging'' function runs during Crazyflie startup and will start all the log blocks listed. As you can see we have some log blocks commented out currently so that we do NOT start those blocks. :3. Create Functions to Read the variable values during runtime (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> float CCrazyflie::magX() { return this->sensorDoubleValue("mag.x"); } float CCrazyflie::magY() { return this->sensorDoubleValue("mag.y"); } float CCrazyflie::magZ() { return this->sensorDoubleValue("mag.z"); } </pre> </code> </blockquote> ::So now we can use these sensor values, from the Firmware, in the Client code with <code>magX1 = cflieCopter1->magX()</code>. This will store the sensor value in the Client-side variable ''magX1''. :4. (OPTIONAL) We can also create a function to stop logging an individual log block in the Client (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::disableMagnetometerLogging() { m_tocLogs->unregisterLoggingBlock("magnetometer"); } </pre> </code> </blockquote> ::This is straightforward, it just tells the client to stop logging this block. :5. (OPTIONAL) And we can stop ALL log blocks in the client as well (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::stopLogging() { this->disableStabilizerLogging(); this->disableGyroscopeLogging(); this->disableAccelerometerLogging(); this->disableBatteryLogging(); // this->disableMagnetometerLogging(); // this->disableAltimeterLogging(); // this->disablePIDOutputLogging(); this->disableRadioRSSILogging(); this->disableMotorLogging(); return true; } </pre> </code> </blockquote> ---- <center> '''Modifications Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 0e86c3b1b20fedde1d87d8f0292de22bfc02dda2 109 105 2016-07-20T17:58:47Z Jnoronha 3 /* MATLAB Parser */ added reminder to finish wikitext text/x-wiki The logging system is the most important analysis tool we have. This allows us to export any variable data we want out to an external text file. This way we can use any data processor to parse the data. (Excel, MATLAB, R, etc.) ==Creating and Using the Log Files== We first need to initialize the log files and prepare them before each test. :1. Create empty File Pointers (code in 'eris_vrpn.cpp') <blockquote> <code> <pre> FILE * outHand = NULL; FILE * out1 = NULL; FILE * out2 = NULL; FILE * out3 = NULL; FILE * out4 = NULL; </pre> </code> </blockquote> :2. Make sure Logging is Enabled (and Basic Logging if desired) <blockquote> <code> <pre> #define USE_VRPN 1 #define USE_KEYBOARD 1 #define USE_PRINTOUT 0 #define USE_LOGGING 1 <---//Enables Full Logging #define USE_BASIC_LOGGING 1 <---//Only logs the necessities (FULL LOGGING MUST BE ENABLED FOR THIS TO WORK) #define USE_PR_YAW_CORRECT 0 #define USE_HAND 1 </pre> </code> </blockquote> :3. Create Log File Header (# = Log File Title, % = List of Variable Names, & = List of Variable Units) ::'''Note 1:''' This example is using BASIC_LOGGING 1, ::'''Note 2:''' Variables and units are separated by a double tab '\t\t' (Does not have to be '\t\t' any delimiter works) <blockquote> <code> <pre> const char * logHeaderHand = "#Hand Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tLoopTime\t\tLoopTimeDelta\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tseconds\t\tseconds\n"; const char * logHeader1 = "#Crazyflie1 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\t\tRadioRSSI\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\t\tstrength\n"; const char * logHeader2 = "#Crazyflie2 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader3 = "#Crazyflie3 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader4 = "#Crazyflie4 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; </pre> </code> </blockquote> :4. Open External .txt file and Print Header into file <blockquote> <code> <pre> #if USE_HAND outHand = fopen("hand.txt", "w"); //Opens text file with write permission if(outHand == NULL) { printf("Could not open hand.log: errno %d\n", errno); exit(-1); } fprintf(outHand, "%s\n", logHeaderHand); //Prints log header into corresponding file #endif if(cflieCopter1) //Checks to see if cflieCopter pointer has been initialized before opening file { out1 = fopen("cflie1.txt", "w"); if(out1 == NULL) { printf("Could not open cflie1.log: errno %d\n", errno); exit(-1); } fprintf(out1, "%s\n", logHeader1); } if(cflieCopter2) { out2 = fopen("cflie2.txt", "w"); if(out2 == NULL) { printf("Could not open cflie2.log:errno %d\n", errno); exit(-1); } fprintf(out2, "%s\n", logHeader2); } if(cflieCopter3) { out3 = fopen("cflie3.txt", "w"); if(out3 == NULL) { printf("Could not open cflie3.log:errno %d\n", errno); exit(-1); } fprintf(out3, "%s\n", logHeader3); } if(cflieCopter4) { out4 = fopen("cflie4.txt", "w"); if(out4 == NULL) { printf("Could not open cflie4.log:errno %d\n", errno); exit(-1); } fprintf(out4, "%s\n", logHeader4); } </pre> </code> </blockquote> :5. Init has Completed (Start Program Loop) Prints Variable values to file... ::'''Note 1:''' This code is run at the end of the Callback for each Crazyflie initialized (Executes once per new data packet) ::'''Note 2:''' This example is using BASIC_LOGGING, and is only showing Crazyflie1's code. <blockquote> <code> <pre> fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); fprintf(out1, "\n"); </pre> </code> </blockquote> :6. Close External .txt files before ending program <blockquote> <code> <pre> #if USE_LOGGING #if USE_HAND fclose(outHand); #endif #if NUM_QUADS >= 1 fclose(out1); #endif #if NUM_QUADS >= 2 fclose(out2); #endif #if NUM_QUADS >= 3 fclose(out3); #endif #if NUM_QUADS >= 4 fclose(out4); #endif #endif </pre> </code> </blockquote> ==MATLAB Parser (TODO)== We use a Matlab script to parse the log files. ==New Client Log Blocks== In the Swarm Client there is a sub-system designed for creating and maintaining Log Blocks. Once you have [[:Firmware#Log Blocks|created a new log block in the Firmware]] that you want to utilize we can do the following: :1. Create an Enable function for the New Log Block (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::enableMagnetometerLogging() { m_tocLogs->registerLoggingBlock("magnetometer", 1000); m_tocLogs->startLogging("mag.x", "magnetometer"); m_tocLogs->startLogging("mag.y", "magnetometer"); m_tocLogs->startLogging("mag.z", "magnetometer"); } </pre> </code> </blockquote> ::This will then register a log block called ''magnetometer'' on the Client, which will be updated every 1000 &mu;s. It will then update the values listed in the block (X, Y, Z of the magnetometer). ::'''Note 1:''' The ''"mag.x"'' term must match the name defined in the Firmware log block (see [[:Firmware#Log Blocks|firmware example 1]]) ::'''Note 2:''' The 2nd input to the ''startLogging'' function needs to match the name of the Client Log block we registered (in this case ''"magnetometer"'') :2. Add the ''enableLogBlock'' function we just made to the list of Log blocks we want at startup (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::startLogging() { // Register the desired sensor readings this->enableStabilizerLogging(); // this->enableGyroscopeLogging(); // this->enableAccelerometerLogging(); this->enableBatteryLogging(); this->enableMagnetometerLogging(); <-----//This is the one we just made // this->enableAltimeterLogging(); // this->enablePIDOutputLogging(); // this->enableRadioRSSILogging(); // this->enableMotorLogging(); return true; } </pre> </code> </blockquote> ::This ''startLogging'' function runs during Crazyflie startup and will start all the log blocks listed. As you can see we have some log blocks commented out currently so that we do NOT start those blocks. :3. Create Functions to Read the variable values during runtime (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> float CCrazyflie::magX() { return this->sensorDoubleValue("mag.x"); } float CCrazyflie::magY() { return this->sensorDoubleValue("mag.y"); } float CCrazyflie::magZ() { return this->sensorDoubleValue("mag.z"); } </pre> </code> </blockquote> ::So now we can use these sensor values, from the Firmware, in the Client code with <code>magX1 = cflieCopter1->magX()</code>. This will store the sensor value in the Client-side variable ''magX1''. :4. (OPTIONAL) We can also create a function to stop logging an individual log block in the Client (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::disableMagnetometerLogging() { m_tocLogs->unregisterLoggingBlock("magnetometer"); } </pre> </code> </blockquote> ::This is straightforward, it just tells the client to stop logging this block. :5. (OPTIONAL) And we can stop ALL log blocks in the client as well (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::stopLogging() { this->disableStabilizerLogging(); this->disableGyroscopeLogging(); this->disableAccelerometerLogging(); this->disableBatteryLogging(); // this->disableMagnetometerLogging(); // this->disableAltimeterLogging(); // this->disablePIDOutputLogging(); this->disableRadioRSSILogging(); this->disableMotorLogging(); return true; } </pre> </code> </blockquote> ---- <center> '''Modifications Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> cffcf9290c8d4c7e3257790700b6aaeb1b45ad54 110 109 2016-07-20T17:59:01Z Jnoronha 3 /* MATLAB Parser (TODO) */ wikitext text/x-wiki The logging system is the most important analysis tool we have. This allows us to export any variable data we want out to an external text file. This way we can use any data processor to parse the data. (Excel, MATLAB, R, etc.) ==Creating and Using the Log Files== We first need to initialize the log files and prepare them before each test. :1. Create empty File Pointers (code in 'eris_vrpn.cpp') <blockquote> <code> <pre> FILE * outHand = NULL; FILE * out1 = NULL; FILE * out2 = NULL; FILE * out3 = NULL; FILE * out4 = NULL; </pre> </code> </blockquote> :2. Make sure Logging is Enabled (and Basic Logging if desired) <blockquote> <code> <pre> #define USE_VRPN 1 #define USE_KEYBOARD 1 #define USE_PRINTOUT 0 #define USE_LOGGING 1 <---//Enables Full Logging #define USE_BASIC_LOGGING 1 <---//Only logs the necessities (FULL LOGGING MUST BE ENABLED FOR THIS TO WORK) #define USE_PR_YAW_CORRECT 0 #define USE_HAND 1 </pre> </code> </blockquote> :3. Create Log File Header (# = Log File Title, % = List of Variable Names, & = List of Variable Units) ::'''Note 1:''' This example is using BASIC_LOGGING 1, ::'''Note 2:''' Variables and units are separated by a double tab '\t\t' (Does not have to be '\t\t' any delimiter works) <blockquote> <code> <pre> const char * logHeaderHand = "#Hand Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tLoopTime\t\tLoopTimeDelta\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tseconds\t\tseconds\n"; const char * logHeader1 = "#Crazyflie1 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\t\tRadioRSSI\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\t\tstrength\n"; const char * logHeader2 = "#Crazyflie2 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader3 = "#Crazyflie3 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader4 = "#Crazyflie4 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; </pre> </code> </blockquote> :4. Open External .txt file and Print Header into file <blockquote> <code> <pre> #if USE_HAND outHand = fopen("hand.txt", "w"); //Opens text file with write permission if(outHand == NULL) { printf("Could not open hand.log: errno %d\n", errno); exit(-1); } fprintf(outHand, "%s\n", logHeaderHand); //Prints log header into corresponding file #endif if(cflieCopter1) //Checks to see if cflieCopter pointer has been initialized before opening file { out1 = fopen("cflie1.txt", "w"); if(out1 == NULL) { printf("Could not open cflie1.log: errno %d\n", errno); exit(-1); } fprintf(out1, "%s\n", logHeader1); } if(cflieCopter2) { out2 = fopen("cflie2.txt", "w"); if(out2 == NULL) { printf("Could not open cflie2.log:errno %d\n", errno); exit(-1); } fprintf(out2, "%s\n", logHeader2); } if(cflieCopter3) { out3 = fopen("cflie3.txt", "w"); if(out3 == NULL) { printf("Could not open cflie3.log:errno %d\n", errno); exit(-1); } fprintf(out3, "%s\n", logHeader3); } if(cflieCopter4) { out4 = fopen("cflie4.txt", "w"); if(out4 == NULL) { printf("Could not open cflie4.log:errno %d\n", errno); exit(-1); } fprintf(out4, "%s\n", logHeader4); } </pre> </code> </blockquote> :5. Init has Completed (Start Program Loop) Prints Variable values to file... ::'''Note 1:''' This code is run at the end of the Callback for each Crazyflie initialized (Executes once per new data packet) ::'''Note 2:''' This example is using BASIC_LOGGING, and is only showing Crazyflie1's code. <blockquote> <code> <pre> fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); fprintf(out1, "\n"); </pre> </code> </blockquote> :6. Close External .txt files before ending program <blockquote> <code> <pre> #if USE_LOGGING #if USE_HAND fclose(outHand); #endif #if NUM_QUADS >= 1 fclose(out1); #endif #if NUM_QUADS >= 2 fclose(out2); #endif #if NUM_QUADS >= 3 fclose(out3); #endif #if NUM_QUADS >= 4 fclose(out4); #endif #endif </pre> </code> </blockquote> ==MATLAB Parser (**TODO**)== We use a Matlab script to parse the log files. ==New Client Log Blocks== In the Swarm Client there is a sub-system designed for creating and maintaining Log Blocks. Once you have [[:Firmware#Log Blocks|created a new log block in the Firmware]] that you want to utilize we can do the following: :1. Create an Enable function for the New Log Block (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::enableMagnetometerLogging() { m_tocLogs->registerLoggingBlock("magnetometer", 1000); m_tocLogs->startLogging("mag.x", "magnetometer"); m_tocLogs->startLogging("mag.y", "magnetometer"); m_tocLogs->startLogging("mag.z", "magnetometer"); } </pre> </code> </blockquote> ::This will then register a log block called ''magnetometer'' on the Client, which will be updated every 1000 &mu;s. It will then update the values listed in the block (X, Y, Z of the magnetometer). ::'''Note 1:''' The ''"mag.x"'' term must match the name defined in the Firmware log block (see [[:Firmware#Log Blocks|firmware example 1]]) ::'''Note 2:''' The 2nd input to the ''startLogging'' function needs to match the name of the Client Log block we registered (in this case ''"magnetometer"'') :2. Add the ''enableLogBlock'' function we just made to the list of Log blocks we want at startup (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::startLogging() { // Register the desired sensor readings this->enableStabilizerLogging(); // this->enableGyroscopeLogging(); // this->enableAccelerometerLogging(); this->enableBatteryLogging(); this->enableMagnetometerLogging(); <-----//This is the one we just made // this->enableAltimeterLogging(); // this->enablePIDOutputLogging(); // this->enableRadioRSSILogging(); // this->enableMotorLogging(); return true; } </pre> </code> </blockquote> ::This ''startLogging'' function runs during Crazyflie startup and will start all the log blocks listed. As you can see we have some log blocks commented out currently so that we do NOT start those blocks. :3. Create Functions to Read the variable values during runtime (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> float CCrazyflie::magX() { return this->sensorDoubleValue("mag.x"); } float CCrazyflie::magY() { return this->sensorDoubleValue("mag.y"); } float CCrazyflie::magZ() { return this->sensorDoubleValue("mag.z"); } </pre> </code> </blockquote> ::So now we can use these sensor values, from the Firmware, in the Client code with <code>magX1 = cflieCopter1->magX()</code>. This will store the sensor value in the Client-side variable ''magX1''. :4. (OPTIONAL) We can also create a function to stop logging an individual log block in the Client (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::disableMagnetometerLogging() { m_tocLogs->unregisterLoggingBlock("magnetometer"); } </pre> </code> </blockquote> ::This is straightforward, it just tells the client to stop logging this block. :5. (OPTIONAL) And we can stop ALL log blocks in the client as well (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::stopLogging() { this->disableStabilizerLogging(); this->disableGyroscopeLogging(); this->disableAccelerometerLogging(); this->disableBatteryLogging(); // this->disableMagnetometerLogging(); // this->disableAltimeterLogging(); // this->disablePIDOutputLogging(); this->disableRadioRSSILogging(); this->disableMotorLogging(); return true; } </pre> </code> </blockquote> ---- <center> '''Modifications Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 52e0eb5cc25b70a5de627471f1b895dce6a5138a 111 110 2016-07-20T17:59:25Z Jnoronha 3 /* MATLAB Parser (**TODO**) */ moved reminder to not the title wikitext text/x-wiki The logging system is the most important analysis tool we have. This allows us to export any variable data we want out to an external text file. This way we can use any data processor to parse the data. (Excel, MATLAB, R, etc.) ==Creating and Using the Log Files== We first need to initialize the log files and prepare them before each test. :1. Create empty File Pointers (code in 'eris_vrpn.cpp') <blockquote> <code> <pre> FILE * outHand = NULL; FILE * out1 = NULL; FILE * out2 = NULL; FILE * out3 = NULL; FILE * out4 = NULL; </pre> </code> </blockquote> :2. Make sure Logging is Enabled (and Basic Logging if desired) <blockquote> <code> <pre> #define USE_VRPN 1 #define USE_KEYBOARD 1 #define USE_PRINTOUT 0 #define USE_LOGGING 1 <---//Enables Full Logging #define USE_BASIC_LOGGING 1 <---//Only logs the necessities (FULL LOGGING MUST BE ENABLED FOR THIS TO WORK) #define USE_PR_YAW_CORRECT 0 #define USE_HAND 1 </pre> </code> </blockquote> :3. Create Log File Header (# = Log File Title, % = List of Variable Names, & = List of Variable Units) ::'''Note 1:''' This example is using BASIC_LOGGING 1, ::'''Note 2:''' Variables and units are separated by a double tab '\t\t' (Does not have to be '\t\t' any delimiter works) <blockquote> <code> <pre> const char * logHeaderHand = "#Hand Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tLoopTime\t\tLoopTimeDelta\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tseconds\t\tseconds\n"; const char * logHeader1 = "#Crazyflie1 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\t\tRadioRSSI\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\t\tstrength\n"; const char * logHeader2 = "#Crazyflie2 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader3 = "#Crazyflie3 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader4 = "#Crazyflie4 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; </pre> </code> </blockquote> :4. Open External .txt file and Print Header into file <blockquote> <code> <pre> #if USE_HAND outHand = fopen("hand.txt", "w"); //Opens text file with write permission if(outHand == NULL) { printf("Could not open hand.log: errno %d\n", errno); exit(-1); } fprintf(outHand, "%s\n", logHeaderHand); //Prints log header into corresponding file #endif if(cflieCopter1) //Checks to see if cflieCopter pointer has been initialized before opening file { out1 = fopen("cflie1.txt", "w"); if(out1 == NULL) { printf("Could not open cflie1.log: errno %d\n", errno); exit(-1); } fprintf(out1, "%s\n", logHeader1); } if(cflieCopter2) { out2 = fopen("cflie2.txt", "w"); if(out2 == NULL) { printf("Could not open cflie2.log:errno %d\n", errno); exit(-1); } fprintf(out2, "%s\n", logHeader2); } if(cflieCopter3) { out3 = fopen("cflie3.txt", "w"); if(out3 == NULL) { printf("Could not open cflie3.log:errno %d\n", errno); exit(-1); } fprintf(out3, "%s\n", logHeader3); } if(cflieCopter4) { out4 = fopen("cflie4.txt", "w"); if(out4 == NULL) { printf("Could not open cflie4.log:errno %d\n", errno); exit(-1); } fprintf(out4, "%s\n", logHeader4); } </pre> </code> </blockquote> :5. Init has Completed (Start Program Loop) Prints Variable values to file... ::'''Note 1:''' This code is run at the end of the Callback for each Crazyflie initialized (Executes once per new data packet) ::'''Note 2:''' This example is using BASIC_LOGGING, and is only showing Crazyflie1's code. <blockquote> <code> <pre> fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); fprintf(out1, "\n"); </pre> </code> </blockquote> :6. Close External .txt files before ending program <blockquote> <code> <pre> #if USE_LOGGING #if USE_HAND fclose(outHand); #endif #if NUM_QUADS >= 1 fclose(out1); #endif #if NUM_QUADS >= 2 fclose(out2); #endif #if NUM_QUADS >= 3 fclose(out3); #endif #if NUM_QUADS >= 4 fclose(out4); #endif #endif </pre> </code> </blockquote> ==MATLAB Parser== '''(**TODO**)''' We use a Matlab script to parse the log files. ==New Client Log Blocks== In the Swarm Client there is a sub-system designed for creating and maintaining Log Blocks. Once you have [[:Firmware#Log Blocks|created a new log block in the Firmware]] that you want to utilize we can do the following: :1. Create an Enable function for the New Log Block (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::enableMagnetometerLogging() { m_tocLogs->registerLoggingBlock("magnetometer", 1000); m_tocLogs->startLogging("mag.x", "magnetometer"); m_tocLogs->startLogging("mag.y", "magnetometer"); m_tocLogs->startLogging("mag.z", "magnetometer"); } </pre> </code> </blockquote> ::This will then register a log block called ''magnetometer'' on the Client, which will be updated every 1000 &mu;s. It will then update the values listed in the block (X, Y, Z of the magnetometer). ::'''Note 1:''' The ''"mag.x"'' term must match the name defined in the Firmware log block (see [[:Firmware#Log Blocks|firmware example 1]]) ::'''Note 2:''' The 2nd input to the ''startLogging'' function needs to match the name of the Client Log block we registered (in this case ''"magnetometer"'') :2. Add the ''enableLogBlock'' function we just made to the list of Log blocks we want at startup (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::startLogging() { // Register the desired sensor readings this->enableStabilizerLogging(); // this->enableGyroscopeLogging(); // this->enableAccelerometerLogging(); this->enableBatteryLogging(); this->enableMagnetometerLogging(); <-----//This is the one we just made // this->enableAltimeterLogging(); // this->enablePIDOutputLogging(); // this->enableRadioRSSILogging(); // this->enableMotorLogging(); return true; } </pre> </code> </blockquote> ::This ''startLogging'' function runs during Crazyflie startup and will start all the log blocks listed. As you can see we have some log blocks commented out currently so that we do NOT start those blocks. :3. Create Functions to Read the variable values during runtime (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> float CCrazyflie::magX() { return this->sensorDoubleValue("mag.x"); } float CCrazyflie::magY() { return this->sensorDoubleValue("mag.y"); } float CCrazyflie::magZ() { return this->sensorDoubleValue("mag.z"); } </pre> </code> </blockquote> ::So now we can use these sensor values, from the Firmware, in the Client code with <code>magX1 = cflieCopter1->magX()</code>. This will store the sensor value in the Client-side variable ''magX1''. :4. (OPTIONAL) We can also create a function to stop logging an individual log block in the Client (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::disableMagnetometerLogging() { m_tocLogs->unregisterLoggingBlock("magnetometer"); } </pre> </code> </blockquote> ::This is straightforward, it just tells the client to stop logging this block. :5. (OPTIONAL) And we can stop ALL log blocks in the client as well (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::stopLogging() { this->disableStabilizerLogging(); this->disableGyroscopeLogging(); this->disableAccelerometerLogging(); this->disableBatteryLogging(); // this->disableMagnetometerLogging(); // this->disableAltimeterLogging(); // this->disablePIDOutputLogging(); this->disableRadioRSSILogging(); this->disableMotorLogging(); return true; } </pre> </code> </blockquote> ---- <center> '''Modifications Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> f9ecb3bf2212ee7f5f2affd41c39342d92faa84c 112 111 2016-07-20T18:00:29Z Jnoronha 3 /* New Client Log Blocks */ short description wikitext text/x-wiki The logging system is the most important analysis tool we have. This allows us to export any variable data we want out to an external text file. This way we can use any data processor to parse the data. (Excel, MATLAB, R, etc.) ==Creating and Using the Log Files== We first need to initialize the log files and prepare them before each test. :1. Create empty File Pointers (code in 'eris_vrpn.cpp') <blockquote> <code> <pre> FILE * outHand = NULL; FILE * out1 = NULL; FILE * out2 = NULL; FILE * out3 = NULL; FILE * out4 = NULL; </pre> </code> </blockquote> :2. Make sure Logging is Enabled (and Basic Logging if desired) <blockquote> <code> <pre> #define USE_VRPN 1 #define USE_KEYBOARD 1 #define USE_PRINTOUT 0 #define USE_LOGGING 1 <---//Enables Full Logging #define USE_BASIC_LOGGING 1 <---//Only logs the necessities (FULL LOGGING MUST BE ENABLED FOR THIS TO WORK) #define USE_PR_YAW_CORRECT 0 #define USE_HAND 1 </pre> </code> </blockquote> :3. Create Log File Header (# = Log File Title, % = List of Variable Names, & = List of Variable Units) ::'''Note 1:''' This example is using BASIC_LOGGING 1, ::'''Note 2:''' Variables and units are separated by a double tab '\t\t' (Does not have to be '\t\t' any delimiter works) <blockquote> <code> <pre> const char * logHeaderHand = "#Hand Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tLoopTime\t\tLoopTimeDelta\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tseconds\t\tseconds\n"; const char * logHeader1 = "#Crazyflie1 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\t\tRadioRSSI\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\t\tstrength\n"; const char * logHeader2 = "#Crazyflie2 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader3 = "#Crazyflie3 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader4 = "#Crazyflie4 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; </pre> </code> </blockquote> :4. Open External .txt file and Print Header into file <blockquote> <code> <pre> #if USE_HAND outHand = fopen("hand.txt", "w"); //Opens text file with write permission if(outHand == NULL) { printf("Could not open hand.log: errno %d\n", errno); exit(-1); } fprintf(outHand, "%s\n", logHeaderHand); //Prints log header into corresponding file #endif if(cflieCopter1) //Checks to see if cflieCopter pointer has been initialized before opening file { out1 = fopen("cflie1.txt", "w"); if(out1 == NULL) { printf("Could not open cflie1.log: errno %d\n", errno); exit(-1); } fprintf(out1, "%s\n", logHeader1); } if(cflieCopter2) { out2 = fopen("cflie2.txt", "w"); if(out2 == NULL) { printf("Could not open cflie2.log:errno %d\n", errno); exit(-1); } fprintf(out2, "%s\n", logHeader2); } if(cflieCopter3) { out3 = fopen("cflie3.txt", "w"); if(out3 == NULL) { printf("Could not open cflie3.log:errno %d\n", errno); exit(-1); } fprintf(out3, "%s\n", logHeader3); } if(cflieCopter4) { out4 = fopen("cflie4.txt", "w"); if(out4 == NULL) { printf("Could not open cflie4.log:errno %d\n", errno); exit(-1); } fprintf(out4, "%s\n", logHeader4); } </pre> </code> </blockquote> :5. Init has Completed (Start Program Loop) Prints Variable values to file... ::'''Note 1:''' This code is run at the end of the Callback for each Crazyflie initialized (Executes once per new data packet) ::'''Note 2:''' This example is using BASIC_LOGGING, and is only showing Crazyflie1's code. <blockquote> <code> <pre> fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); fprintf(out1, "\n"); </pre> </code> </blockquote> :6. Close External .txt files before ending program <blockquote> <code> <pre> #if USE_LOGGING #if USE_HAND fclose(outHand); #endif #if NUM_QUADS >= 1 fclose(out1); #endif #if NUM_QUADS >= 2 fclose(out2); #endif #if NUM_QUADS >= 3 fclose(out3); #endif #if NUM_QUADS >= 4 fclose(out4); #endif #endif </pre> </code> </blockquote> ==MATLAB Parser== '''(**TODO**)''' We use a Matlab script to parse the log files. ==New Client Log Blocks== In the Swarm Client there is a sub-system designed for creating and maintaining Log Blocks. Once you have [[:Firmware#Log Blocks|created a new log block in the Firmware]] that you want to utilize we can do the following: :1. Create an Enable function for the New Log Block (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::enableMagnetometerLogging() { m_tocLogs->registerLoggingBlock("magnetometer", 1000); m_tocLogs->startLogging("mag.x", "magnetometer"); m_tocLogs->startLogging("mag.y", "magnetometer"); m_tocLogs->startLogging("mag.z", "magnetometer"); } </pre> </code> </blockquote> ::This will then register a log block called ''magnetometer'' on the Client, which will be updated every 1000 &mu;s. It will then update the values listed in the block (X, Y, Z of the magnetometer). ::'''Note 1:''' The ''"mag.x"'' term must match the name defined in the Firmware log block (see [[:Firmware#Log Blocks|firmware example 1]]) ::'''Note 2:''' The 2nd input to the ''startLogging'' function needs to match the name of the Client Log block we registered (in this case ''"magnetometer"'') :2. Add the ''enableLogBlock'' function we just made to the list of Log blocks we want at startup (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::startLogging() { // Register the desired sensor readings this->enableStabilizerLogging(); // this->enableGyroscopeLogging(); // this->enableAccelerometerLogging(); this->enableBatteryLogging(); this->enableMagnetometerLogging(); <-----//This is the one we just made // this->enableAltimeterLogging(); // this->enablePIDOutputLogging(); // this->enableRadioRSSILogging(); // this->enableMotorLogging(); return true; } </pre> </code> </blockquote> ::This ''startLogging'' function runs during Crazyflie startup and will start all the log blocks listed. As you can see we have some log blocks commented out currently so that we do NOT start those blocks. :3. Create Functions to Read the variable values during runtime (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> float CCrazyflie::magX() { return this->sensorDoubleValue("mag.x"); } float CCrazyflie::magY() { return this->sensorDoubleValue("mag.y"); } float CCrazyflie::magZ() { return this->sensorDoubleValue("mag.z"); } </pre> </code> </blockquote> ::So now we can use these sensor values, from the Firmware, in the Client code with <code>magX1 = cflieCopter1->magX()</code>. This will store the sensor value in the Client-side variable ''magX1''. :4. (OPTIONAL) We can also create a function to stop logging an individual log block in the Client (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::disableMagnetometerLogging() { m_tocLogs->unregisterLoggingBlock("magnetometer"); } </pre> </code> </blockquote> ::This is straightforward, it just tells the client to stop logging this block. :5. (OPTIONAL) And we can stop ALL log blocks in the client as well (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::stopLogging() { this->disableStabilizerLogging(); this->disableGyroscopeLogging(); this->disableAccelerometerLogging(); this->disableBatteryLogging(); // this->disableMagnetometerLogging(); // this->disableAltimeterLogging(); // this->disablePIDOutputLogging(); this->disableRadioRSSILogging(); this->disableMotorLogging(); return true; } </pre> </code> </blockquote> ::This will disable ALL the logging blocks included in the list. ---- <center> '''Modifications Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> e70cdfb00d153e69dd85c031913ec6919410ad4c 113 112 2016-07-20T18:01:32Z Jnoronha 3 /* New Client Log Blocks */ added space between directory and wiki page wikitext text/x-wiki The logging system is the most important analysis tool we have. This allows us to export any variable data we want out to an external text file. This way we can use any data processor to parse the data. (Excel, MATLAB, R, etc.) ==Creating and Using the Log Files== We first need to initialize the log files and prepare them before each test. :1. Create empty File Pointers (code in 'eris_vrpn.cpp') <blockquote> <code> <pre> FILE * outHand = NULL; FILE * out1 = NULL; FILE * out2 = NULL; FILE * out3 = NULL; FILE * out4 = NULL; </pre> </code> </blockquote> :2. Make sure Logging is Enabled (and Basic Logging if desired) <blockquote> <code> <pre> #define USE_VRPN 1 #define USE_KEYBOARD 1 #define USE_PRINTOUT 0 #define USE_LOGGING 1 <---//Enables Full Logging #define USE_BASIC_LOGGING 1 <---//Only logs the necessities (FULL LOGGING MUST BE ENABLED FOR THIS TO WORK) #define USE_PR_YAW_CORRECT 0 #define USE_HAND 1 </pre> </code> </blockquote> :3. Create Log File Header (# = Log File Title, % = List of Variable Names, & = List of Variable Units) ::'''Note 1:''' This example is using BASIC_LOGGING 1, ::'''Note 2:''' Variables and units are separated by a double tab '\t\t' (Does not have to be '\t\t' any delimiter works) <blockquote> <code> <pre> const char * logHeaderHand = "#Hand Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tLoopTime\t\tLoopTimeDelta\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tseconds\t\tseconds\n"; const char * logHeader1 = "#Crazyflie1 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\t\tRadioRSSI\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\t\tstrength\n"; const char * logHeader2 = "#Crazyflie2 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader3 = "#Crazyflie3 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader4 = "#Crazyflie4 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; </pre> </code> </blockquote> :4. Open External .txt file and Print Header into file <blockquote> <code> <pre> #if USE_HAND outHand = fopen("hand.txt", "w"); //Opens text file with write permission if(outHand == NULL) { printf("Could not open hand.log: errno %d\n", errno); exit(-1); } fprintf(outHand, "%s\n", logHeaderHand); //Prints log header into corresponding file #endif if(cflieCopter1) //Checks to see if cflieCopter pointer has been initialized before opening file { out1 = fopen("cflie1.txt", "w"); if(out1 == NULL) { printf("Could not open cflie1.log: errno %d\n", errno); exit(-1); } fprintf(out1, "%s\n", logHeader1); } if(cflieCopter2) { out2 = fopen("cflie2.txt", "w"); if(out2 == NULL) { printf("Could not open cflie2.log:errno %d\n", errno); exit(-1); } fprintf(out2, "%s\n", logHeader2); } if(cflieCopter3) { out3 = fopen("cflie3.txt", "w"); if(out3 == NULL) { printf("Could not open cflie3.log:errno %d\n", errno); exit(-1); } fprintf(out3, "%s\n", logHeader3); } if(cflieCopter4) { out4 = fopen("cflie4.txt", "w"); if(out4 == NULL) { printf("Could not open cflie4.log:errno %d\n", errno); exit(-1); } fprintf(out4, "%s\n", logHeader4); } </pre> </code> </blockquote> :5. Init has Completed (Start Program Loop) Prints Variable values to file... ::'''Note 1:''' This code is run at the end of the Callback for each Crazyflie initialized (Executes once per new data packet) ::'''Note 2:''' This example is using BASIC_LOGGING, and is only showing Crazyflie1's code. <blockquote> <code> <pre> fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); fprintf(out1, "\n"); </pre> </code> </blockquote> :6. Close External .txt files before ending program <blockquote> <code> <pre> #if USE_LOGGING #if USE_HAND fclose(outHand); #endif #if NUM_QUADS >= 1 fclose(out1); #endif #if NUM_QUADS >= 2 fclose(out2); #endif #if NUM_QUADS >= 3 fclose(out3); #endif #if NUM_QUADS >= 4 fclose(out4); #endif #endif </pre> </code> </blockquote> ==MATLAB Parser== '''(**TODO**)''' We use a Matlab script to parse the log files. ==New Client Log Blocks== In the Swarm Client there is a sub-system designed for creating and maintaining Log Blocks. Once you have [[:Firmware#Log Blocks|created a new log block in the Firmware]] that you want to utilize we can do the following: :1. Create an Enable function for the New Log Block (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::enableMagnetometerLogging() { m_tocLogs->registerLoggingBlock("magnetometer", 1000); m_tocLogs->startLogging("mag.x", "magnetometer"); m_tocLogs->startLogging("mag.y", "magnetometer"); m_tocLogs->startLogging("mag.z", "magnetometer"); } </pre> </code> </blockquote> ::This will then register a log block called ''magnetometer'' on the Client, which will be updated every 1000 &mu;s. It will then update the values listed in the block (X, Y, Z of the magnetometer). ::'''Note 1:''' The ''"mag.x"'' term must match the name defined in the Firmware log block (see [[:Firmware#Log Blocks|firmware example 1]]) ::'''Note 2:''' The 2nd input to the ''startLogging'' function needs to match the name of the Client Log block we registered (in this case ''"magnetometer"'') :2. Add the ''enableLogBlock'' function we just made to the list of Log blocks we want at startup (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::startLogging() { // Register the desired sensor readings this->enableStabilizerLogging(); // this->enableGyroscopeLogging(); // this->enableAccelerometerLogging(); this->enableBatteryLogging(); this->enableMagnetometerLogging(); <-----//This is the one we just made // this->enableAltimeterLogging(); // this->enablePIDOutputLogging(); // this->enableRadioRSSILogging(); // this->enableMotorLogging(); return true; } </pre> </code> </blockquote> ::This ''startLogging'' function runs during Crazyflie startup and will start all the log blocks listed. As you can see we have some log blocks commented out currently so that we do NOT start those blocks. :3. Create Functions to Read the variable values during runtime (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> float CCrazyflie::magX() { return this->sensorDoubleValue("mag.x"); } float CCrazyflie::magY() { return this->sensorDoubleValue("mag.y"); } float CCrazyflie::magZ() { return this->sensorDoubleValue("mag.z"); } </pre> </code> </blockquote> ::So now we can use these sensor values, from the Firmware, in the Client code with <code>magX1 = cflieCopter1->magX()</code>. This will store the sensor value in the Client-side variable ''magX1''. :4. (OPTIONAL) We can also create a function to stop logging an individual log block in the Client (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::disableMagnetometerLogging() { m_tocLogs->unregisterLoggingBlock("magnetometer"); } </pre> </code> </blockquote> ::This is straightforward, it just tells the client to stop logging this block. :5. (OPTIONAL) And we can stop ALL log blocks in the client as well (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::stopLogging() { this->disableStabilizerLogging(); this->disableGyroscopeLogging(); this->disableAccelerometerLogging(); this->disableBatteryLogging(); // this->disableMagnetometerLogging(); // this->disableAltimeterLogging(); // this->disablePIDOutputLogging(); this->disableRadioRSSILogging(); this->disableMotorLogging(); return true; } </pre> </code> </blockquote> ::This will disable ALL the logging blocks included in the list. ---- <center> '''Modifications Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> a7eb1a0b9c72d960e26c4fdf86bbf714188a1acf 114 113 2016-07-20T18:05:56Z Jnoronha 3 /* New Client Log Blocks */ changed directory to include both modifications and main pages wikitext text/x-wiki The logging system is the most important analysis tool we have. This allows us to export any variable data we want out to an external text file. This way we can use any data processor to parse the data. (Excel, MATLAB, R, etc.) ==Creating and Using the Log Files== We first need to initialize the log files and prepare them before each test. :1. Create empty File Pointers (code in 'eris_vrpn.cpp') <blockquote> <code> <pre> FILE * outHand = NULL; FILE * out1 = NULL; FILE * out2 = NULL; FILE * out3 = NULL; FILE * out4 = NULL; </pre> </code> </blockquote> :2. Make sure Logging is Enabled (and Basic Logging if desired) <blockquote> <code> <pre> #define USE_VRPN 1 #define USE_KEYBOARD 1 #define USE_PRINTOUT 0 #define USE_LOGGING 1 <---//Enables Full Logging #define USE_BASIC_LOGGING 1 <---//Only logs the necessities (FULL LOGGING MUST BE ENABLED FOR THIS TO WORK) #define USE_PR_YAW_CORRECT 0 #define USE_HAND 1 </pre> </code> </blockquote> :3. Create Log File Header (# = Log File Title, % = List of Variable Names, & = List of Variable Units) ::'''Note 1:''' This example is using BASIC_LOGGING 1, ::'''Note 2:''' Variables and units are separated by a double tab '\t\t' (Does not have to be '\t\t' any delimiter works) <blockquote> <code> <pre> const char * logHeaderHand = "#Hand Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tLoopTime\t\tLoopTimeDelta\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tseconds\t\tseconds\n"; const char * logHeader1 = "#Crazyflie1 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\t\tRadioRSSI\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\t\tstrength\n"; const char * logHeader2 = "#Crazyflie2 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader3 = "#Crazyflie3 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader4 = "#Crazyflie4 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; </pre> </code> </blockquote> :4. Open External .txt file and Print Header into file <blockquote> <code> <pre> #if USE_HAND outHand = fopen("hand.txt", "w"); //Opens text file with write permission if(outHand == NULL) { printf("Could not open hand.log: errno %d\n", errno); exit(-1); } fprintf(outHand, "%s\n", logHeaderHand); //Prints log header into corresponding file #endif if(cflieCopter1) //Checks to see if cflieCopter pointer has been initialized before opening file { out1 = fopen("cflie1.txt", "w"); if(out1 == NULL) { printf("Could not open cflie1.log: errno %d\n", errno); exit(-1); } fprintf(out1, "%s\n", logHeader1); } if(cflieCopter2) { out2 = fopen("cflie2.txt", "w"); if(out2 == NULL) { printf("Could not open cflie2.log:errno %d\n", errno); exit(-1); } fprintf(out2, "%s\n", logHeader2); } if(cflieCopter3) { out3 = fopen("cflie3.txt", "w"); if(out3 == NULL) { printf("Could not open cflie3.log:errno %d\n", errno); exit(-1); } fprintf(out3, "%s\n", logHeader3); } if(cflieCopter4) { out4 = fopen("cflie4.txt", "w"); if(out4 == NULL) { printf("Could not open cflie4.log:errno %d\n", errno); exit(-1); } fprintf(out4, "%s\n", logHeader4); } </pre> </code> </blockquote> :5. Init has Completed (Start Program Loop) Prints Variable values to file... ::'''Note 1:''' This code is run at the end of the Callback for each Crazyflie initialized (Executes once per new data packet) ::'''Note 2:''' This example is using BASIC_LOGGING, and is only showing Crazyflie1's code. <blockquote> <code> <pre> fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); fprintf(out1, "\n"); </pre> </code> </blockquote> :6. Close External .txt files before ending program <blockquote> <code> <pre> #if USE_LOGGING #if USE_HAND fclose(outHand); #endif #if NUM_QUADS >= 1 fclose(out1); #endif #if NUM_QUADS >= 2 fclose(out2); #endif #if NUM_QUADS >= 3 fclose(out3); #endif #if NUM_QUADS >= 4 fclose(out4); #endif #endif </pre> </code> </blockquote> ==MATLAB Parser== '''(**TODO**)''' We use a Matlab script to parse the log files. ==New Client Log Blocks== In the Swarm Client there is a sub-system designed for creating and maintaining Log Blocks. Once you have [[:Firmware#Log Blocks|created a new log block in the Firmware]] that you want to utilize we can do the following: :1. Create an Enable function for the New Log Block (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::enableMagnetometerLogging() { m_tocLogs->registerLoggingBlock("magnetometer", 1000); m_tocLogs->startLogging("mag.x", "magnetometer"); m_tocLogs->startLogging("mag.y", "magnetometer"); m_tocLogs->startLogging("mag.z", "magnetometer"); } </pre> </code> </blockquote> ::This will then register a log block called ''magnetometer'' on the Client, which will be updated every 1000 &mu;s. It will then update the values listed in the block (X, Y, Z of the magnetometer). ::'''Note 1:''' The ''"mag.x"'' term must match the name defined in the Firmware log block (see [[:Firmware#Log Blocks|firmware example 1]]) ::'''Note 2:''' The 2nd input to the ''startLogging'' function needs to match the name of the Client Log block we registered (in this case ''"magnetometer"'') :2. Add the ''enableLogBlock'' function we just made to the list of Log blocks we want at startup (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::startLogging() { // Register the desired sensor readings this->enableStabilizerLogging(); // this->enableGyroscopeLogging(); // this->enableAccelerometerLogging(); this->enableBatteryLogging(); this->enableMagnetometerLogging(); <-----//This is the one we just made // this->enableAltimeterLogging(); // this->enablePIDOutputLogging(); // this->enableRadioRSSILogging(); // this->enableMotorLogging(); return true; } </pre> </code> </blockquote> ::This ''startLogging'' function runs during Crazyflie startup and will start all the log blocks listed. As you can see we have some log blocks commented out currently so that we do NOT start those blocks. :3. Create Functions to Read the variable values during runtime (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> float CCrazyflie::magX() { return this->sensorDoubleValue("mag.x"); } float CCrazyflie::magY() { return this->sensorDoubleValue("mag.y"); } float CCrazyflie::magZ() { return this->sensorDoubleValue("mag.z"); } </pre> </code> </blockquote> ::So now we can use these sensor values, from the Firmware, in the Client code with <code>magX1 = cflieCopter1->magX()</code>. This will store the sensor value in the Client-side variable ''magX1''. :4. (OPTIONAL) We can also create a function to stop logging an individual log block in the Client (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::disableMagnetometerLogging() { m_tocLogs->unregisterLoggingBlock("magnetometer"); } </pre> </code> </blockquote> ::This is straightforward, it just tells the client to stop logging this block. :5. (OPTIONAL) And we can stop ALL log blocks in the client as well (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::stopLogging() { this->disableStabilizerLogging(); this->disableGyroscopeLogging(); this->disableAccelerometerLogging(); this->disableBatteryLogging(); // this->disableMagnetometerLogging(); // this->disableAltimeterLogging(); // this->disablePIDOutputLogging(); this->disableRadioRSSILogging(); this->disableMotorLogging(); return true; } </pre> </code> </blockquote> ::This will disable ALL the logging blocks included in the list. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> f3742349fa6ff6711419a830cfd7fe6ad08e5e8d 115 114 2016-07-20T18:13:37Z Jnoronha 3 /* Creating and Using the Log Files */ Changed title wikitext text/x-wiki The logging system is the most important analysis tool we have. This allows us to export any variable data we want out to an external text file. This way we can use any data processor to parse the data. (Excel, MATLAB, R, etc.) ==Client-Side External Log Files== We first need to initialize the log files and prepare them before each test. :1. Create empty File Pointers (code in 'eris_vrpn.cpp') <blockquote> <code> <pre> FILE * outHand = NULL; FILE * out1 = NULL; FILE * out2 = NULL; FILE * out3 = NULL; FILE * out4 = NULL; </pre> </code> </blockquote> :2. Make sure Logging is Enabled (and Basic Logging if desired) <blockquote> <code> <pre> #define USE_VRPN 1 #define USE_KEYBOARD 1 #define USE_PRINTOUT 0 #define USE_LOGGING 1 <---//Enables Full Logging #define USE_BASIC_LOGGING 1 <---//Only logs the necessities (FULL LOGGING MUST BE ENABLED FOR THIS TO WORK) #define USE_PR_YAW_CORRECT 0 #define USE_HAND 1 </pre> </code> </blockquote> :3. Create Log File Header (# = Log File Title, % = List of Variable Names, & = List of Variable Units) ::'''Note 1:''' This example is using BASIC_LOGGING 1, ::'''Note 2:''' Variables and units are separated by a double tab '\t\t' (Does not have to be '\t\t' any delimiter works) <blockquote> <code> <pre> const char * logHeaderHand = "#Hand Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tLoopTime\t\tLoopTimeDelta\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tseconds\t\tseconds\n"; const char * logHeader1 = "#Crazyflie1 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\t\tRadioRSSI\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\t\tstrength\n"; const char * logHeader2 = "#Crazyflie2 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader3 = "#Crazyflie3 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader4 = "#Crazyflie4 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; </pre> </code> </blockquote> :4. Open External .txt file and Print Header into file <blockquote> <code> <pre> #if USE_HAND outHand = fopen("hand.txt", "w"); //Opens text file with write permission if(outHand == NULL) { printf("Could not open hand.log: errno %d\n", errno); exit(-1); } fprintf(outHand, "%s\n", logHeaderHand); //Prints log header into corresponding file #endif if(cflieCopter1) //Checks to see if cflieCopter pointer has been initialized before opening file { out1 = fopen("cflie1.txt", "w"); if(out1 == NULL) { printf("Could not open cflie1.log: errno %d\n", errno); exit(-1); } fprintf(out1, "%s\n", logHeader1); } if(cflieCopter2) { out2 = fopen("cflie2.txt", "w"); if(out2 == NULL) { printf("Could not open cflie2.log:errno %d\n", errno); exit(-1); } fprintf(out2, "%s\n", logHeader2); } if(cflieCopter3) { out3 = fopen("cflie3.txt", "w"); if(out3 == NULL) { printf("Could not open cflie3.log:errno %d\n", errno); exit(-1); } fprintf(out3, "%s\n", logHeader3); } if(cflieCopter4) { out4 = fopen("cflie4.txt", "w"); if(out4 == NULL) { printf("Could not open cflie4.log:errno %d\n", errno); exit(-1); } fprintf(out4, "%s\n", logHeader4); } </pre> </code> </blockquote> :5. Init has Completed (Start Program Loop) Prints Variable values to file... ::'''Note 1:''' This code is run at the end of the Callback for each Crazyflie initialized (Executes once per new data packet) ::'''Note 2:''' This example is using BASIC_LOGGING, and is only showing Crazyflie1's code. <blockquote> <code> <pre> fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); fprintf(out1, "\n"); </pre> </code> </blockquote> :6. Close External .txt files before ending program <blockquote> <code> <pre> #if USE_LOGGING #if USE_HAND fclose(outHand); #endif #if NUM_QUADS >= 1 fclose(out1); #endif #if NUM_QUADS >= 2 fclose(out2); #endif #if NUM_QUADS >= 3 fclose(out3); #endif #if NUM_QUADS >= 4 fclose(out4); #endif #endif </pre> </code> </blockquote> ==MATLAB Parser== '''(**TODO**)''' We use a Matlab script to parse the log files. ==New Client Log Blocks== In the Swarm Client there is a sub-system designed for creating and maintaining Log Blocks. Once you have [[:Firmware#Log Blocks|created a new log block in the Firmware]] that you want to utilize we can do the following: :1. Create an Enable function for the New Log Block (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::enableMagnetometerLogging() { m_tocLogs->registerLoggingBlock("magnetometer", 1000); m_tocLogs->startLogging("mag.x", "magnetometer"); m_tocLogs->startLogging("mag.y", "magnetometer"); m_tocLogs->startLogging("mag.z", "magnetometer"); } </pre> </code> </blockquote> ::This will then register a log block called ''magnetometer'' on the Client, which will be updated every 1000 &mu;s. It will then update the values listed in the block (X, Y, Z of the magnetometer). ::'''Note 1:''' The ''"mag.x"'' term must match the name defined in the Firmware log block (see [[:Firmware#Log Blocks|firmware example 1]]) ::'''Note 2:''' The 2nd input to the ''startLogging'' function needs to match the name of the Client Log block we registered (in this case ''"magnetometer"'') :2. Add the ''enableLogBlock'' function we just made to the list of Log blocks we want at startup (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::startLogging() { // Register the desired sensor readings this->enableStabilizerLogging(); // this->enableGyroscopeLogging(); // this->enableAccelerometerLogging(); this->enableBatteryLogging(); this->enableMagnetometerLogging(); <-----//This is the one we just made // this->enableAltimeterLogging(); // this->enablePIDOutputLogging(); // this->enableRadioRSSILogging(); // this->enableMotorLogging(); return true; } </pre> </code> </blockquote> ::This ''startLogging'' function runs during Crazyflie startup and will start all the log blocks listed. As you can see we have some log blocks commented out currently so that we do NOT start those blocks. :3. Create Functions to Read the variable values during runtime (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> float CCrazyflie::magX() { return this->sensorDoubleValue("mag.x"); } float CCrazyflie::magY() { return this->sensorDoubleValue("mag.y"); } float CCrazyflie::magZ() { return this->sensorDoubleValue("mag.z"); } </pre> </code> </blockquote> ::So now we can use these sensor values, from the Firmware, in the Client code with <code>magX1 = cflieCopter1->magX()</code>. This will store the sensor value in the Client-side variable ''magX1''. :4. (OPTIONAL) We can also create a function to stop logging an individual log block in the Client (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::disableMagnetometerLogging() { m_tocLogs->unregisterLoggingBlock("magnetometer"); } </pre> </code> </blockquote> ::This is straightforward, it just tells the client to stop logging this block. :5. (OPTIONAL) And we can stop ALL log blocks in the client as well (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::stopLogging() { this->disableStabilizerLogging(); this->disableGyroscopeLogging(); this->disableAccelerometerLogging(); this->disableBatteryLogging(); // this->disableMagnetometerLogging(); // this->disableAltimeterLogging(); // this->disablePIDOutputLogging(); this->disableRadioRSSILogging(); this->disableMotorLogging(); return true; } </pre> </code> </blockquote> ::This will disable ALL the logging blocks included in the list. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 78b8807e20310b15ceaa7df25890966d6e95d9f9 117 115 2016-07-20T18:23:24Z Jnoronha 3 /* New Client Log Blocks */ Added FAQ to directory wikitext text/x-wiki The logging system is the most important analysis tool we have. This allows us to export any variable data we want out to an external text file. This way we can use any data processor to parse the data. (Excel, MATLAB, R, etc.) ==Client-Side External Log Files== We first need to initialize the log files and prepare them before each test. :1. Create empty File Pointers (code in 'eris_vrpn.cpp') <blockquote> <code> <pre> FILE * outHand = NULL; FILE * out1 = NULL; FILE * out2 = NULL; FILE * out3 = NULL; FILE * out4 = NULL; </pre> </code> </blockquote> :2. Make sure Logging is Enabled (and Basic Logging if desired) <blockquote> <code> <pre> #define USE_VRPN 1 #define USE_KEYBOARD 1 #define USE_PRINTOUT 0 #define USE_LOGGING 1 <---//Enables Full Logging #define USE_BASIC_LOGGING 1 <---//Only logs the necessities (FULL LOGGING MUST BE ENABLED FOR THIS TO WORK) #define USE_PR_YAW_CORRECT 0 #define USE_HAND 1 </pre> </code> </blockquote> :3. Create Log File Header (# = Log File Title, % = List of Variable Names, & = List of Variable Units) ::'''Note 1:''' This example is using BASIC_LOGGING 1, ::'''Note 2:''' Variables and units are separated by a double tab '\t\t' (Does not have to be '\t\t' any delimiter works) <blockquote> <code> <pre> const char * logHeaderHand = "#Hand Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tLoopTime\t\tLoopTimeDelta\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tseconds\t\tseconds\n"; const char * logHeader1 = "#Crazyflie1 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\t\tRadioRSSI\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\t\tstrength\n"; const char * logHeader2 = "#Crazyflie2 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader3 = "#Crazyflie3 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader4 = "#Crazyflie4 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; </pre> </code> </blockquote> :4. Open External .txt file and Print Header into file <blockquote> <code> <pre> #if USE_HAND outHand = fopen("hand.txt", "w"); //Opens text file with write permission if(outHand == NULL) { printf("Could not open hand.log: errno %d\n", errno); exit(-1); } fprintf(outHand, "%s\n", logHeaderHand); //Prints log header into corresponding file #endif if(cflieCopter1) //Checks to see if cflieCopter pointer has been initialized before opening file { out1 = fopen("cflie1.txt", "w"); if(out1 == NULL) { printf("Could not open cflie1.log: errno %d\n", errno); exit(-1); } fprintf(out1, "%s\n", logHeader1); } if(cflieCopter2) { out2 = fopen("cflie2.txt", "w"); if(out2 == NULL) { printf("Could not open cflie2.log:errno %d\n", errno); exit(-1); } fprintf(out2, "%s\n", logHeader2); } if(cflieCopter3) { out3 = fopen("cflie3.txt", "w"); if(out3 == NULL) { printf("Could not open cflie3.log:errno %d\n", errno); exit(-1); } fprintf(out3, "%s\n", logHeader3); } if(cflieCopter4) { out4 = fopen("cflie4.txt", "w"); if(out4 == NULL) { printf("Could not open cflie4.log:errno %d\n", errno); exit(-1); } fprintf(out4, "%s\n", logHeader4); } </pre> </code> </blockquote> :5. Init has Completed (Start Program Loop) Prints Variable values to file... ::'''Note 1:''' This code is run at the end of the Callback for each Crazyflie initialized (Executes once per new data packet) ::'''Note 2:''' This example is using BASIC_LOGGING, and is only showing Crazyflie1's code. <blockquote> <code> <pre> fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); fprintf(out1, "\n"); </pre> </code> </blockquote> :6. Close External .txt files before ending program <blockquote> <code> <pre> #if USE_LOGGING #if USE_HAND fclose(outHand); #endif #if NUM_QUADS >= 1 fclose(out1); #endif #if NUM_QUADS >= 2 fclose(out2); #endif #if NUM_QUADS >= 3 fclose(out3); #endif #if NUM_QUADS >= 4 fclose(out4); #endif #endif </pre> </code> </blockquote> ==MATLAB Parser== '''(**TODO**)''' We use a Matlab script to parse the log files. ==New Client Log Blocks== In the Swarm Client there is a sub-system designed for creating and maintaining Log Blocks. Once you have [[:Firmware#Log Blocks|created a new log block in the Firmware]] that you want to utilize we can do the following: :1. Create an Enable function for the New Log Block (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::enableMagnetometerLogging() { m_tocLogs->registerLoggingBlock("magnetometer", 1000); m_tocLogs->startLogging("mag.x", "magnetometer"); m_tocLogs->startLogging("mag.y", "magnetometer"); m_tocLogs->startLogging("mag.z", "magnetometer"); } </pre> </code> </blockquote> ::This will then register a log block called ''magnetometer'' on the Client, which will be updated every 1000 &mu;s. It will then update the values listed in the block (X, Y, Z of the magnetometer). ::'''Note 1:''' The ''"mag.x"'' term must match the name defined in the Firmware log block (see [[:Firmware#Log Blocks|firmware example 1]]) ::'''Note 2:''' The 2nd input to the ''startLogging'' function needs to match the name of the Client Log block we registered (in this case ''"magnetometer"'') :2. Add the ''enableLogBlock'' function we just made to the list of Log blocks we want at startup (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::startLogging() { // Register the desired sensor readings this->enableStabilizerLogging(); // this->enableGyroscopeLogging(); // this->enableAccelerometerLogging(); this->enableBatteryLogging(); this->enableMagnetometerLogging(); <-----//This is the one we just made // this->enableAltimeterLogging(); // this->enablePIDOutputLogging(); // this->enableRadioRSSILogging(); // this->enableMotorLogging(); return true; } </pre> </code> </blockquote> ::This ''startLogging'' function runs during Crazyflie startup and will start all the log blocks listed. As you can see we have some log blocks commented out currently so that we do NOT start those blocks. :3. Create Functions to Read the variable values during runtime (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> float CCrazyflie::magX() { return this->sensorDoubleValue("mag.x"); } float CCrazyflie::magY() { return this->sensorDoubleValue("mag.y"); } float CCrazyflie::magZ() { return this->sensorDoubleValue("mag.z"); } </pre> </code> </blockquote> ::So now we can use these sensor values, from the Firmware, in the Client code with <code>magX1 = cflieCopter1->magX()</code>. This will store the sensor value in the Client-side variable ''magX1''. :4. (OPTIONAL) We can also create a function to stop logging an individual log block in the Client (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::disableMagnetometerLogging() { m_tocLogs->unregisterLoggingBlock("magnetometer"); } </pre> </code> </blockquote> ::This is straightforward, it just tells the client to stop logging this block. :5. (OPTIONAL) And we can stop ALL log blocks in the client as well (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::stopLogging() { this->disableStabilizerLogging(); this->disableGyroscopeLogging(); this->disableAccelerometerLogging(); this->disableBatteryLogging(); // this->disableMagnetometerLogging(); // this->disableAltimeterLogging(); // this->disablePIDOutputLogging(); this->disableRadioRSSILogging(); this->disableMotorLogging(); return true; } </pre> </code> </blockquote> ::This will disable ALL the logging blocks included in the list. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> e84925610055eec1271eb4b67a199d9ea45c58d1 Firmware 0 26 102 58 2016-07-20T16:04:35Z Jnoronha 3 Added Firmware Log block examples wikitext text/x-wiki Not much work has been done in the Firmware yet. (as of 7/20/16) The few things we have been able to successfully modify are: #Creating New Log Blocks #Modifying the Default Yaw Mode #Adding and Modifying Parameter Values ==Log Blocks== In the Crazyflie Firmware there is a generalized logging framework that allows us to make any group of variables into a log block. It makes things very easy to log. Here are a few examples: :1. Magnometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(mag) LOG_ADD(LOG_FLOAT, x, &mag.x) LOG_ADD(LOG_FLOAT, y, &mag.y) LOG_ADD(LOG_FLOAT, z, &mag.z) LOG_GROUP_STOP(mag) </pre> </code> </blockquote> :So with this code we have created a log block called 'mag' and it contains the X, Y, and Z measurements from the magnetometer sensor. :2. Accelerometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(acc) LOG_ADD(LOG_FLOAT, x, &acc.x) LOG_ADD(LOG_FLOAT, y, &acc.y) LOG_ADD(LOG_FLOAT, z, &acc.z) LOG_ADD(LOG_FLOAT, zw, &accWZ) LOG_ADD(LOG_FLOAT, mag2, &accMAG) LOG_GROUP_STOP(acc) </pre> </code> </blockquote> :So just like in the magnetometer block, here we have created a log group called 'acc' and inside this group we are logging the variables for the accelerometer's X, Y, and Z values as well as 2 other gravity based variables used for thrust compensation. ===Using New Log Blocks in Swarm Client=== ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] </center> a617ebab2c936ac90612d8d5a5820ceb715e0132 104 102 2016-07-20T16:45:45Z Jnoronha 3 /* Log Blocks */ linked to using new log blocks in Client wikitext text/x-wiki Not much work has been done in the Firmware yet. (as of 7/20/16) The few things we have been able to successfully modify are: #Creating New Log Blocks #Modifying the Default Yaw Mode #Adding and Modifying Parameter Values ==Log Blocks== In the Crazyflie Firmware there is a generalized logging framework that allows us to make any group of variables into a log block. It makes things very easy to log. Here are a few examples: :1. Magnometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(mag) LOG_ADD(LOG_FLOAT, x, &mag.x) LOG_ADD(LOG_FLOAT, y, &mag.y) LOG_ADD(LOG_FLOAT, z, &mag.z) LOG_GROUP_STOP(mag) </pre> </code> </blockquote> :So with this code we have created a log block called 'mag' and it contains the X, Y, and Z measurements from the magnetometer sensor. :2. Accelerometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(acc) LOG_ADD(LOG_FLOAT, x, &acc.x) LOG_ADD(LOG_FLOAT, y, &acc.y) LOG_ADD(LOG_FLOAT, z, &acc.z) LOG_ADD(LOG_FLOAT, zw, &accWZ) LOG_ADD(LOG_FLOAT, mag2, &accMAG) LOG_GROUP_STOP(acc) </pre> </code> </blockquote> :So just like in the magnetometer block, here we have created a log group called 'acc' and inside this group we are logging the variables for the accelerometer's X, Y, and Z values as well as 2 other gravity based variables used for thrust compensation. ===Using New Log Blocks in Swarm Client=== Now that we have these new log blocks, we can [[:Logging#Starting New Log Blocks|use log blocks in the Client]] ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] </center> d7f8949456c1aabce7db5a489d19be0b6bc94af3 106 104 2016-07-20T16:48:07Z Jnoronha 3 /* Using New Log Blocks in Swarm Client */ fixed link to client log blocks wikitext text/x-wiki Not much work has been done in the Firmware yet. (as of 7/20/16) The few things we have been able to successfully modify are: #Creating New Log Blocks #Modifying the Default Yaw Mode #Adding and Modifying Parameter Values ==Log Blocks== In the Crazyflie Firmware there is a generalized logging framework that allows us to make any group of variables into a log block. It makes things very easy to log. Here are a few examples: :1. Magnometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(mag) LOG_ADD(LOG_FLOAT, x, &mag.x) LOG_ADD(LOG_FLOAT, y, &mag.y) LOG_ADD(LOG_FLOAT, z, &mag.z) LOG_GROUP_STOP(mag) </pre> </code> </blockquote> :So with this code we have created a log block called 'mag' and it contains the X, Y, and Z measurements from the magnetometer sensor. :2. Accelerometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(acc) LOG_ADD(LOG_FLOAT, x, &acc.x) LOG_ADD(LOG_FLOAT, y, &acc.y) LOG_ADD(LOG_FLOAT, z, &acc.z) LOG_ADD(LOG_FLOAT, zw, &accWZ) LOG_ADD(LOG_FLOAT, mag2, &accMAG) LOG_GROUP_STOP(acc) </pre> </code> </blockquote> :So just like in the magnetometer block, here we have created a log group called 'acc' and inside this group we are logging the variables for the accelerometer's X, Y, and Z values as well as 2 other gravity based variables used for thrust compensation. ===Using New Log Blocks in Swarm Client=== Now that we have these new log blocks, we can [[:Logging#New Client Log Blocks|use log blocks in the Client]] ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] </center> 69be7e1c0a17bcc21ae22fb768da2134e60ca2fb 107 106 2016-07-20T16:49:18Z Jnoronha 3 /* Using New Log Blocks in Swarm Client */ added in firmware detail wikitext text/x-wiki Not much work has been done in the Firmware yet. (as of 7/20/16) The few things we have been able to successfully modify are: #Creating New Log Blocks #Modifying the Default Yaw Mode #Adding and Modifying Parameter Values ==Log Blocks== In the Crazyflie Firmware there is a generalized logging framework that allows us to make any group of variables into a log block. It makes things very easy to log. Here are a few examples: :1. Magnometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(mag) LOG_ADD(LOG_FLOAT, x, &mag.x) LOG_ADD(LOG_FLOAT, y, &mag.y) LOG_ADD(LOG_FLOAT, z, &mag.z) LOG_GROUP_STOP(mag) </pre> </code> </blockquote> :So with this code we have created a log block called 'mag' and it contains the X, Y, and Z measurements from the magnetometer sensor. :2. Accelerometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(acc) LOG_ADD(LOG_FLOAT, x, &acc.x) LOG_ADD(LOG_FLOAT, y, &acc.y) LOG_ADD(LOG_FLOAT, z, &acc.z) LOG_ADD(LOG_FLOAT, zw, &accWZ) LOG_ADD(LOG_FLOAT, mag2, &accMAG) LOG_GROUP_STOP(acc) </pre> </code> </blockquote> :So just like in the magnetometer block, here we have created a log group called 'acc' and inside this group we are logging the variables for the accelerometer's X, Y, and Z values as well as 2 other gravity based variables used for thrust compensation. ===Using New Log Blocks in Swarm Client=== Now that we have these new log blocks in the Firmware, we can [[:Logging#New Client Log Blocks|use log blocks in the Client]] ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] </center> 2840a8d63acbd8c6532ba4db045c933e92d03aa8 108 107 2016-07-20T17:05:49Z Jnoronha 3 /* Log Blocks */ wikitext text/x-wiki Not much work has been done in the Firmware yet. (as of 7/20/16) The few things we have been able to successfully modify are: #Creating New Log Blocks #Modifying the Default Yaw Mode #Adding and Modifying Parameter Values ==Log Blocks== In the Crazyflie Firmware there is a generalized logging framework that allows us to make any group of variables into a log block. It makes things very easy to log. Here are a few examples: :Ex. 1. Magnometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(mag) LOG_ADD(LOG_FLOAT, x, &mag.x) LOG_ADD(LOG_FLOAT, y, &mag.y) LOG_ADD(LOG_FLOAT, z, &mag.z) LOG_GROUP_STOP(mag) </pre> </code> </blockquote> ::So with this code we have created a log block called 'mag' and it contains the X, Y, and Z measurements from the magnetometer sensor. :Ex. 2. Accelerometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(acc) LOG_ADD(LOG_FLOAT, x, &acc.x) LOG_ADD(LOG_FLOAT, y, &acc.y) LOG_ADD(LOG_FLOAT, z, &acc.z) LOG_ADD(LOG_FLOAT, zw, &accWZ) LOG_ADD(LOG_FLOAT, mag2, &accMAG) LOG_GROUP_STOP(acc) </pre> </code> </blockquote> ::Just like in the magnetometer block, here we have created a log group called 'acc' and inside this group we are logging the variables for the accelerometer's X, Y, and Z values as well as 2 other gravity based variables used for thrust compensation. ===Using New Log Blocks in Swarm Client=== Now that we have these new log blocks in the Firmware, we can [[:Logging#New Client Log Blocks|use log blocks in the Client]] ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] </center> 50cfa13915f3ec51b2274ac5a9603af8e2a343c0 116 108 2016-07-20T18:14:51Z Jnoronha 3 /* Log Blocks */ changed title wikitext text/x-wiki Not much work has been done in the Firmware yet. (as of 7/20/16) The few things we have been able to successfully modify are: #Creating New Log Blocks #Modifying the Default Yaw Mode #Adding and Modifying Parameter Values ==New Firmware Log Blocks== In the Crazyflie Firmware there is a generalized logging framework that allows us to make any group of variables into a log block. It makes things very easy to log. Here are a few examples: :Ex. 1. Magnometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(mag) LOG_ADD(LOG_FLOAT, x, &mag.x) LOG_ADD(LOG_FLOAT, y, &mag.y) LOG_ADD(LOG_FLOAT, z, &mag.z) LOG_GROUP_STOP(mag) </pre> </code> </blockquote> ::So with this code we have created a log block called 'mag' and it contains the X, Y, and Z measurements from the magnetometer sensor. :Ex. 2. Accelerometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(acc) LOG_ADD(LOG_FLOAT, x, &acc.x) LOG_ADD(LOG_FLOAT, y, &acc.y) LOG_ADD(LOG_FLOAT, z, &acc.z) LOG_ADD(LOG_FLOAT, zw, &accWZ) LOG_ADD(LOG_FLOAT, mag2, &accMAG) LOG_GROUP_STOP(acc) </pre> </code> </blockquote> ::Just like in the magnetometer block, here we have created a log group called 'acc' and inside this group we are logging the variables for the accelerometer's X, Y, and Z values as well as 2 other gravity based variables used for thrust compensation. ===Using New Log Blocks in Swarm Client=== Now that we have these new log blocks in the Firmware, we can [[:Logging#New Client Log Blocks|use log blocks in the Client]] ---- <center> [[Crazyflie Swarm]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] </center> 2c8d0cbc2b4ec90d9df69b013a192642b0946fc4 121 116 2016-07-20T18:58:57Z Jnoronha 3 /* Using New Log Blocks in Swarm Client */ modified directory wikitext text/x-wiki Not much work has been done in the Firmware yet. (as of 7/20/16) The few things we have been able to successfully modify are: #Creating New Log Blocks #Modifying the Default Yaw Mode #Adding and Modifying Parameter Values ==New Firmware Log Blocks== In the Crazyflie Firmware there is a generalized logging framework that allows us to make any group of variables into a log block. It makes things very easy to log. Here are a few examples: :Ex. 1. Magnometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(mag) LOG_ADD(LOG_FLOAT, x, &mag.x) LOG_ADD(LOG_FLOAT, y, &mag.y) LOG_ADD(LOG_FLOAT, z, &mag.z) LOG_GROUP_STOP(mag) </pre> </code> </blockquote> ::So with this code we have created a log block called 'mag' and it contains the X, Y, and Z measurements from the magnetometer sensor. :Ex. 2. Accelerometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(acc) LOG_ADD(LOG_FLOAT, x, &acc.x) LOG_ADD(LOG_FLOAT, y, &acc.y) LOG_ADD(LOG_FLOAT, z, &acc.z) LOG_ADD(LOG_FLOAT, zw, &accWZ) LOG_ADD(LOG_FLOAT, mag2, &accMAG) LOG_GROUP_STOP(acc) </pre> </code> </blockquote> ::Just like in the magnetometer block, here we have created a log group called 'acc' and inside this group we are logging the variables for the accelerometer's X, Y, and Z values as well as 2 other gravity based variables used for thrust compensation. ===Using New Log Blocks in Swarm Client=== Now that we have these new log blocks in the Firmware, we can [[:Logging#New Client Log Blocks|use log blocks in the Client]] ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 4c6303e2774532187b647a83bdd64fb1aa04f7e8 123 121 2016-07-21T17:50:51Z Jnoronha 3 finished yaw modification section (still missing final FIRMWARE yaw change code) wikitext text/x-wiki Not much work has been done in the Firmware yet (as of 7/20/16). The few things we have been able to successfully modify are: #Creating New Log Blocks #Modifying the Default Yaw Mode #Adding and Modifying Parameter Values ==New Firmware Log Blocks== In the Crazyflie Firmware there is a generalized logging framework that allows us to make any group of variables into a log block. It makes things very easy to log. Here are a few examples: :Ex. 1. Magnometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(mag) LOG_ADD(LOG_FLOAT, x, &mag.x) LOG_ADD(LOG_FLOAT, y, &mag.y) LOG_ADD(LOG_FLOAT, z, &mag.z) LOG_GROUP_STOP(mag) </pre> </code> </blockquote> ::So with this code we have created a log block called 'mag' and it contains the X, Y, and Z measurements from the magnetometer sensor. :Ex. 2. Accelerometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(acc) LOG_ADD(LOG_FLOAT, x, &acc.x) LOG_ADD(LOG_FLOAT, y, &acc.y) LOG_ADD(LOG_FLOAT, z, &acc.z) LOG_ADD(LOG_FLOAT, zw, &accWZ) LOG_ADD(LOG_FLOAT, mag2, &accMAG) LOG_GROUP_STOP(acc) </pre> </code> </blockquote> ::Just like in the magnetometer block, here we have created a log group called 'acc' and inside this group we are logging the variables for the accelerometer's X, Y, and Z values as well as 2 other gravity based variables used for thrust compensation. ===Using New Log Blocks in Swarm Client=== Now that we have these new log blocks in the Firmware, we can [[:Logging#New Client Log Blocks|use log blocks in the Client]] ==Modify the Default Yaw Mode== There are 3 types of Yaw Modes available in the Firmware (as of 7/21/16), as shown (code in ''Firmware > modules > interface > commander.h'') <blockquote> <code> <pre> typedef enum { CAREFREE = 0, // Yaw is locked to world coordinates thus heading stays the same when yaw rotates PLUSMODE = 1, // Plus-mode. Motor M1 is defined as front XMODE = 2, // X-mode. M1 & M4 is defined as front } YawModeType; </pre> </code> </blockquote> :'''Note:''' The default mode for the Crazyflie 2.0 is ''XMODE''. The ''PLUSMODE'' is default for the Crazyflie 1.0, but can still be used on the Crazyflie 2.0 if desired. ===Carefree Mode=== ''CAREFREE'' mode is what our Crazyflie 2.0's are using, this mode applies a transformation to the Pitch and Roll setpoints depending on the angle of Yaw. We used to perform this calculation on the Client like this (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> #if USE_PR_YAW_CORRECT //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION (_/57.2958 converts DEG to RADIANS) xError2 = cos(correctedYaw2 / 57.2958)*(xPositionDesired2 - xPosition2) - sin(correctedYaw2 / 57.2958)*(yPositionDesired2 - yPosition2); yError2 = sin(correctedYaw2 / 57.2958)*(xPositionDesired2 - xPosition2) + cos(correctedYaw2 / 57.2958)*(yPositionDesired2 - yPosition2); #else xError2 = xPositionDesired2 - xPosition2; yError2 = yPositionDesired2 - yPosition2; #endif controllerSetXYError(&pidCtrl2, xError2, yError2); </pre> </code> </blockquote> This is no longer necessary on the Client because this is the exact same calculation ''CAREFREE'' mode performs on the Firmware. So this reduces the computation done on the Client in each Crazyflie Callback. ====Changing Yaw Mode in Firmware==== To change the Yaw Mode to ''CAREFREE'' mode we had to make the modification shown (code in ''Firmware > modules > src > commander.c''): <blockquote> <code> <pre> ***INSERT CODE CHANGE*** </pre> </code> </blockquote> ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 969c0c11b2bc09f87f24fbddbb3aa22b9fdb0acf 124 123 2016-07-21T18:11:54Z Jnoronha 3 Finished Params section wikitext text/x-wiki Not much work has been done in the Firmware yet (as of 7/20/16). The few things we have been able to successfully modify are: #Creating New Log Blocks #Modifying the Default Yaw Mode #Adding and Modifying Parameter Values ==New Firmware Log Blocks== In the Crazyflie Firmware there is a generalized logging framework that allows us to make any group of variables into a log block. It makes things very easy to log. Here are a few examples: :'''IMPORTANT:''' If you want to create new Log groups in a file, make sure you include <code>#include "log.h"</code> at the top of the file. :Ex. 1. Magnometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(mag) LOG_ADD(LOG_FLOAT, x, &mag.x) LOG_ADD(LOG_FLOAT, y, &mag.y) LOG_ADD(LOG_FLOAT, z, &mag.z) LOG_GROUP_STOP(mag) </pre> </code> </blockquote> ::So with this code we have created a log block called 'mag' and it contains the X, Y, and Z measurements from the magnetometer sensor. :Ex. 2. Accelerometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(acc) LOG_ADD(LOG_FLOAT, x, &acc.x) LOG_ADD(LOG_FLOAT, y, &acc.y) LOG_ADD(LOG_FLOAT, z, &acc.z) LOG_ADD(LOG_FLOAT, zw, &accWZ) LOG_ADD(LOG_FLOAT, mag2, &accMAG) LOG_GROUP_STOP(acc) </pre> </code> </blockquote> ::Just like in the magnetometer block, here we have created a log group called 'acc' and inside this group we are logging the variables for the accelerometer's X, Y, and Z values as well as 2 other gravity based variables used for thrust compensation. ===Using New Log Blocks in Swarm Client=== Now that we have these new log blocks in the Firmware, we can [[:Logging#New Client Log Blocks|use log blocks in the Client]] ==Modify the Default Yaw Mode== There are 3 types of Yaw Modes available in the Firmware (as of 7/21/16), as shown (code in ''Firmware > modules > interface > commander.h'') <blockquote> <code> <pre> typedef enum { CAREFREE = 0, // Yaw is locked to world coordinates thus heading stays the same when yaw rotates PLUSMODE = 1, // Plus-mode. Motor M1 is defined as front XMODE = 2, // X-mode. M1 & M4 is defined as front } YawModeType; </pre> </code> </blockquote> :'''Note:''' The default mode for the Crazyflie 2.0 is ''XMODE''. The ''PLUSMODE'' is default for the Crazyflie 1.0, but can still be used on the Crazyflie 2.0 if desired. ===Carefree Mode=== ''CAREFREE'' mode is what our Crazyflie 2.0's are using, this mode applies a transformation to the Pitch and Roll setpoints depending on the angle of Yaw. We used to perform this calculation on the Client like this (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> #if USE_PR_YAW_CORRECT //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION (_/57.2958 converts DEG to RADIANS) xError2 = cos(correctedYaw2 / 57.2958)*(xPositionDesired2 - xPosition2) - sin(correctedYaw2 / 57.2958)*(yPositionDesired2 - yPosition2); yError2 = sin(correctedYaw2 / 57.2958)*(xPositionDesired2 - xPosition2) + cos(correctedYaw2 / 57.2958)*(yPositionDesired2 - yPosition2); #else xError2 = xPositionDesired2 - xPosition2; yError2 = yPositionDesired2 - yPosition2; #endif controllerSetXYError(&pidCtrl2, xError2, yError2); </pre> </code> </blockquote> This is no longer necessary on the Client because this is the exact same calculation ''CAREFREE'' mode performs on the Firmware. So this reduces the computation done on the Client in each Crazyflie Callback. ====Changing Yaw Mode in Firmware==== To change the Yaw Mode to ''CAREFREE'' mode we had to make the modification shown (code in ''Firmware > modules > src > commander.c''): <blockquote> <code> <pre> ***INSERT CODE CHANGE*** </pre> </code> </blockquote> ==New Firmware Parameter Groups== Parameter groups are very similar to Log groups with a few key differences. An example of a Parameter group is shown (code in ''Firmware > modules > src > commander.c''): :'''IMPORTANT:''' If you want to create new Parameter groups in a file, make sure you include <code>#include "param.h"</code> at the top of the file. <blockquote> <code> <pre> // Params for flight modes PARAM_GROUP_START(flightmode) PARAM_ADD(PARAM_UINT8, althold, &altHoldMode) PARAM_ADD(PARAM_UINT8, yawMode, &yawMode) PARAM_ADD(PARAM_UINT8, yawRst, &carefreeResetFront) PARAM_ADD(PARAM_UINT8, stabModeRoll, &stabilizationModeRoll) PARAM_ADD(PARAM_UINT8, stabModePitch, &stabilizationModePitch) PARAM_ADD(PARAM_UINT8, stabModeYaw, &stabilizationModeYaw) PARAM_GROUP_STOP(flightmode) </pre> </code> </blockquote> :So we create a parameter group called ''flightmode'' that contains the parameters listed. The difference between Log variables and Param variables is that for Param variables you need to specify the variable type (''PARAM_UINT8'' shown in the example). Some User Friendly Param Types are shown below (you can find more complex Param types in ''Firmware > modules > interface > param.h''). <blockquote> <code> <pre> // User-friendly macros #define PARAM_UINT8 (PARAM_1BYTE | PARAM_TYPE_INT | PARAM_UNSIGNED) #define PARAM_INT8 (PARAM_1BYTE | PARAM_TYPE_INT | PARAM_SIGNED) #define PARAM_UINT16 (PARAM_2BYTES | PARAM_TYPE_INT | PARAM_UNSIGNED) #define PARAM_INT16 (PARAM_2BYTES | PARAM_TYPE_INT | PARAM_SIGNED) #define PARAM_UINT32 (PARAM_4BYTES | PARAM_TYPE_INT | PARAM_UNSIGNED) #define PARAM_INT32 (PARAM_4BYTES | PARAM_TYPE_INT | PARAM_SIGNED) </pre> </code> </blockquote> ===Using Param Groups in Client=== This is not implemented yet (as of 7/21/16) but would be very nice to have. If someone would like to attempt to create this you can see the Bitcraze Wiki page on the [https://wiki.bitcraze.io/doc:crazyflie:crtp:param Params Protocol] for help on how to implement this. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 1e5dc859f68b1233cdd841890a33a3aab03cd34e 125 124 2016-07-21T18:12:59Z Jnoronha 3 /* Using Param Groups in Client */ added potential applications to Client Param system wikitext text/x-wiki Not much work has been done in the Firmware yet (as of 7/20/16). The few things we have been able to successfully modify are: #Creating New Log Blocks #Modifying the Default Yaw Mode #Adding and Modifying Parameter Values ==New Firmware Log Blocks== In the Crazyflie Firmware there is a generalized logging framework that allows us to make any group of variables into a log block. It makes things very easy to log. Here are a few examples: :'''IMPORTANT:''' If you want to create new Log groups in a file, make sure you include <code>#include "log.h"</code> at the top of the file. :Ex. 1. Magnometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(mag) LOG_ADD(LOG_FLOAT, x, &mag.x) LOG_ADD(LOG_FLOAT, y, &mag.y) LOG_ADD(LOG_FLOAT, z, &mag.z) LOG_GROUP_STOP(mag) </pre> </code> </blockquote> ::So with this code we have created a log block called 'mag' and it contains the X, Y, and Z measurements from the magnetometer sensor. :Ex. 2. Accelerometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(acc) LOG_ADD(LOG_FLOAT, x, &acc.x) LOG_ADD(LOG_FLOAT, y, &acc.y) LOG_ADD(LOG_FLOAT, z, &acc.z) LOG_ADD(LOG_FLOAT, zw, &accWZ) LOG_ADD(LOG_FLOAT, mag2, &accMAG) LOG_GROUP_STOP(acc) </pre> </code> </blockquote> ::Just like in the magnetometer block, here we have created a log group called 'acc' and inside this group we are logging the variables for the accelerometer's X, Y, and Z values as well as 2 other gravity based variables used for thrust compensation. ===Using New Log Blocks in Swarm Client=== Now that we have these new log blocks in the Firmware, we can [[:Logging#New Client Log Blocks|use log blocks in the Client]] ==Modify the Default Yaw Mode== There are 3 types of Yaw Modes available in the Firmware (as of 7/21/16), as shown (code in ''Firmware > modules > interface > commander.h'') <blockquote> <code> <pre> typedef enum { CAREFREE = 0, // Yaw is locked to world coordinates thus heading stays the same when yaw rotates PLUSMODE = 1, // Plus-mode. Motor M1 is defined as front XMODE = 2, // X-mode. M1 & M4 is defined as front } YawModeType; </pre> </code> </blockquote> :'''Note:''' The default mode for the Crazyflie 2.0 is ''XMODE''. The ''PLUSMODE'' is default for the Crazyflie 1.0, but can still be used on the Crazyflie 2.0 if desired. ===Carefree Mode=== ''CAREFREE'' mode is what our Crazyflie 2.0's are using, this mode applies a transformation to the Pitch and Roll setpoints depending on the angle of Yaw. We used to perform this calculation on the Client like this (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> #if USE_PR_YAW_CORRECT //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION (_/57.2958 converts DEG to RADIANS) xError2 = cos(correctedYaw2 / 57.2958)*(xPositionDesired2 - xPosition2) - sin(correctedYaw2 / 57.2958)*(yPositionDesired2 - yPosition2); yError2 = sin(correctedYaw2 / 57.2958)*(xPositionDesired2 - xPosition2) + cos(correctedYaw2 / 57.2958)*(yPositionDesired2 - yPosition2); #else xError2 = xPositionDesired2 - xPosition2; yError2 = yPositionDesired2 - yPosition2; #endif controllerSetXYError(&pidCtrl2, xError2, yError2); </pre> </code> </blockquote> This is no longer necessary on the Client because this is the exact same calculation ''CAREFREE'' mode performs on the Firmware. So this reduces the computation done on the Client in each Crazyflie Callback. ====Changing Yaw Mode in Firmware==== To change the Yaw Mode to ''CAREFREE'' mode we had to make the modification shown (code in ''Firmware > modules > src > commander.c''): <blockquote> <code> <pre> ***INSERT CODE CHANGE*** </pre> </code> </blockquote> ==New Firmware Parameter Groups== Parameter groups are very similar to Log groups with a few key differences. An example of a Parameter group is shown (code in ''Firmware > modules > src > commander.c''): :'''IMPORTANT:''' If you want to create new Parameter groups in a file, make sure you include <code>#include "param.h"</code> at the top of the file. <blockquote> <code> <pre> // Params for flight modes PARAM_GROUP_START(flightmode) PARAM_ADD(PARAM_UINT8, althold, &altHoldMode) PARAM_ADD(PARAM_UINT8, yawMode, &yawMode) PARAM_ADD(PARAM_UINT8, yawRst, &carefreeResetFront) PARAM_ADD(PARAM_UINT8, stabModeRoll, &stabilizationModeRoll) PARAM_ADD(PARAM_UINT8, stabModePitch, &stabilizationModePitch) PARAM_ADD(PARAM_UINT8, stabModeYaw, &stabilizationModeYaw) PARAM_GROUP_STOP(flightmode) </pre> </code> </blockquote> :So we create a parameter group called ''flightmode'' that contains the parameters listed. The difference between Log variables and Param variables is that for Param variables you need to specify the variable type (''PARAM_UINT8'' shown in the example). Some User Friendly Param Types are shown below (you can find more complex Param types in ''Firmware > modules > interface > param.h''). <blockquote> <code> <pre> // User-friendly macros #define PARAM_UINT8 (PARAM_1BYTE | PARAM_TYPE_INT | PARAM_UNSIGNED) #define PARAM_INT8 (PARAM_1BYTE | PARAM_TYPE_INT | PARAM_SIGNED) #define PARAM_UINT16 (PARAM_2BYTES | PARAM_TYPE_INT | PARAM_UNSIGNED) #define PARAM_INT16 (PARAM_2BYTES | PARAM_TYPE_INT | PARAM_SIGNED) #define PARAM_UINT32 (PARAM_4BYTES | PARAM_TYPE_INT | PARAM_UNSIGNED) #define PARAM_INT32 (PARAM_4BYTES | PARAM_TYPE_INT | PARAM_SIGNED) </pre> </code> </blockquote> ===Using Param Groups in Client=== This is not implemented yet (as of 7/21/16) but would be very nice to have. We could then tune Firmware PID constants without needing to flash the Firmware each time and much more. If someone would like to attempt to create this you can see the Bitcraze Wiki page on the [https://wiki.bitcraze.io/doc:crazyflie:crtp:param Params Protocol] for help on how to implement this. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 6c7d53aea4ca764fbe773469f8de180f9a20b678 FAQ 0 40 118 2016-07-20T18:23:34Z Jnoronha 3 Added first few questions and directory wikitext text/x-wiki Here you can find some Frequently Asked Questions: :1. How do I change the Radio Channel? ::Find out here: [[:USB Radio#Changing Radio Channel|Changing the Radio Channel]] :2. How do I use Log Blocks? ::*Creating and using [[:Logging#Client-Side External Log Files|External Client-side Log Files]] ::*Creating [[:Firmware#New Firmware Log Blocks|New Log Blocks in Firmware]] ::*Creating and Using [[:Logging#New Client Log Blocks|New Log Blocks in Client]] :3. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 25bc2aae2645ae601c63447288f8106304219bc4 135 118 2016-07-22T17:32:03Z Jnoronha 3 Added a couple more questions wikitext text/x-wiki Here you can find some Frequently Asked Questions: :1. How do I change the Radio Channel? ::Find out here: [[:USB Radio#Changing Radio Channel|Changing the Radio Channel]] :2. How do I use Log Blocks? ::*Creating and using [[:Logging#Client-Side External Log Files|External Client-side Log Files]] ::*Creating [[:Firmware#New Firmware Log Blocks|New Log Blocks in Firmware]] ::*Creating and Using [[:Logging#New Client Log Blocks|New Log Blocks in Client]] :3. I just want to run the code, how do I run it? ::See [[:PC Client Software#Using the Swarm Client|Using the Swarm Client]] :4. What are the Keyboard Commands for flying the Crazyflie? ::You can find a full list of all the Key Commands in [[:Keyboard Commands]] ::(Alternatively: See '''Step 4''' of [[:PC Client Software#Using the Swarm Client|Using the Swarm Client]]) ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 75c2d00e31e1c3b729798eac25859c89d1e839e0 136 135 2016-07-22T17:33:45Z Jnoronha 3 bolded questions wikitext text/x-wiki Here you can find some Frequently Asked Questions: :'''1. How do I change the Radio Channel?''' ::Find out here: [[:USB Radio#Changing Radio Channel|Changing the Radio Channel]] :'''2. How do I use Log Blocks?''' ::*Creating and using [[:Logging#Client-Side External Log Files|External Client-side Log Files]] ::*Creating [[:Firmware#New Firmware Log Blocks|New Log Blocks in Firmware]] ::*Creating and Using [[:Logging#New Client Log Blocks|New Log Blocks in Client]] :'''3. I just want to run the code, how do I run it?''' ::See [[:PC Client Software#Using the Swarm Client|Using the Swarm Client]] :'''4. What are the Keyboard Commands for flying the Crazyflie?''' ::You can find a full list of all the Key Commands in [[:Keyboard Commands]] ::(Alternatively: See '''Step 4''' of [[:PC Client Software#Using the Swarm Client|Using the Swarm Client]]) ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> c132db8e6f9a754f6b95a90f29ff841bf7fc7917 PC Client Software 0 25 119 96 2016-07-20T18:58:11Z Jnoronha 3 /* Using the Swarm Client */ added directory wikitext text/x-wiki The PC Client software comes in many forms. The out-of-the-box Client is written in Python and has a Graphical User Interface (GUI). The GUI is well suited for beginners, but can only support a single Radio and a single Crazyflie at a time. The easiest way to start out is with the [https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze Virtual Machine (VM)], which comes with all the files and dependencies pre-installed and can run on any computer (Windows, Mac, Linux, etc.). For more advanced users who want to use the swarm capabilities of our platform will have to use the [[#Swarm Client|Swarm Client]] we developed in C and C++. ==[https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze VM]== ('''Note:''' The VM is updated frequently so the information below may be different than the current VM) The Bitcraze wiki has a tutorial on [https://wiki.bitcraze.io/projects:virtualmachine:tutorials:vmware-win7 installing the VM]. Along with another tutorial on how to get started [https://www.bitcraze.io/getting-started-with-development/ using the VM]. These are both very simple starting guides that will help you become familiar with the VM. ===Crazyflie Client GUI=== On the VM you can find the Crazyflie Client Graphical User Interface (GUI). To run the Client you want to open a terminal and navigate to <code>projects/''''FIND PATH''''</code> and then run the command <code>sudo ./bin/cfclient</code> (Alternatively, you can use the desktop to navigate to the folder and open a terminal there) Once you do that you should see something similar to this: [[Image:DefaultCrazyflieGUIMainScreen.JPG|500px]] This is the main screen of the Client GUI and there are many tabs and features that you can access directly from this screen. The most important parts of this screen are the following: #Connect Button #Bootloader (Crazyflie Drop Down -> Bootloader) #Plotter Tab #Log Blocks Tab #Parameters Tab ====Connect Button==== This is where you will scan for Crazyflies that are powered ON. All Crazyflies not already connected will show up in the popup [[Image:DefaultCrazyflieGUIConnectScreen.JPG|400px]] We get a return that says <code>radio://0/45/2M</code>, this line is the identifier string of the Crazyflie we are trying to connect to. What this is saying is that we got a return from a Radio (Radio 0 specifically), from a Crazyflie on Channel 45 using a data rate of 2Mbps. ====Bootloader==== This where you can install new Firmware to the Crazyflie. [[Image:DefaultCrazyflieGUIBootloader.JPG|500px]] The first thing you'll need to update is to build the Firmware version you want into a .bin file. You can do this by just running the <code>make</code> command in terminal while located inside the Firmware directory you have modified. Once you have that .bin file built you: #Open the bootloader shown #Hold down the power button on the Crazyflie 2.0 for around 3 seconds until the 2 blue LED's flash and alternate. This puts the Crazyflie in bootloader mode. ('''NOTE:''' Recommend having '''ALL other Crazyflies OFF''' or else it could accidentally flash both Crazyflies.) #Then hit ''Initiate bootloader cold boot'' (it should connect to the Crazyflie in bootloader mode after a few seconds, Status will change from 'Not Connected' to 'Connected') #Hit ''Browse'' and find the .bin file you built earlier. #Then click ''Program'' and wait for the progress bar to complete. #Restart the Crazyflie in Firmware mode and make sure it starts up normally, if something seems wrong just repeat steps 2 through 6 again. ====Logging Tab==== Once you connect to a Crazyflie you can monitor certain log variables that have been set up. You will see a plot of the data similar to this: [[Image:DefaultCrazyflieGUILoggerScreen.JPG|400px]] On this screen we can do the following things: *Dropdown Menu at the top of the screen **Select which log block you want to plot on screen. *Scale the X-axis of the plot by: **Range **Number of Samples **Time in Seconds **Manually *Scale the Y-axis by: **Automatically **Manual Range ====Parameters Tab==== This tab displays all the parameters currently set up on the Crazyflie Firmware. Once you connect to a Crazyflie it lists these parameters in a table format similar to below: [[Image:DefaultCrazyflieGUIParametersScreen.JPG|400px]] For each parameter we get its Name, Variable Type, Access Type (Read/Write), and its Current Value. We can also modify the parameter values on this screen in real-time and the changes will be sent to the Crazyflie automatically. ('''Note:''' Any parameter changes made on this screen are NOT preserved when you turn OFF the Crazyflie.) ==Swarm Client== The swarm Client is a re-creation of the Original Client but programmed in C and C++. The benefit of this is that *We use a unified language between Client and Firmware *Easily migrate this platform to any linux distribution that can install the Crazyflie dependencies. **Our platform code itself requires only the VRPN libraries and a generic C compiler. ===Using the Swarm Client=== The Swarm Client uses the terminal interface for User Input. [[Image:CrazyflieTerminalInitial.png|400px]] Here we see what the initial Terminal looks like before we do anything. :1. The first thing you want to do before any testing is to run the <code>sudo make</code> command in the Swarm Client directory. (Yes, the 'sudo' is necessary) ::This will make sure you have all the necessary dependencies, that the code is error free, and then it will build an executable (.exe) file of the Swarm Client code. An error free make will look something like this: ::[[Image:CrazyflieTerminalPostMake.png|400px]] ::There will be warnings, but those don't cause any issues right now. :2. Pre-Test Checklist ::*Camera System is Turned on and Crazyflie Trackables are opened and visible. ::*Radios are plugged into the USB Ports on the Client computer. ::*Crazyflies are ON and NOT in an Error State. :3. Run the executable file using the command <code>sudo ./eris_vrpn</code> in the same directory (Yes, the 'sudo' is necessary). This will start the program initialization and a bunch of status info will flood the screen. You will know the program is ready for input when you see the following: ::[[Image:CrazyflieTerminalProgramStarted.png|400px]] ::This means that the Crazyflie yaw has been synchronized with the Camera system and they are ready to fly. :4. Input a Keyboard Command ::This will depend on what you have programmed as the keyboard input commands. As of 7/19/16 we have the following Keyboard Commands active: ::*'1' - Rotates Yaw of Crazyflie1 +45 degrees ::*'2' - Rotates Yaw of Crazyflie1 -45 degrees ::*'q' - Ends Main Loop (OBSOLETE - Replaced with ctrl + c) ::*'e' - Landing Mode (for ALL Crazyflies) ::*'t' - Crazyflie1 Take-Off ::*'y' - Crazyflie2 Take-Off ::*'u' - Crazyflie3 Take-Off ::*'i' - Crazyflie4 Take-Off ::*'h' - Hand Gesture Mode (for ALL Crazyflies) ::*'m' - Mirror Mode (for ALL Crazyflies) ::*ctrl+c - Quits Program, performs all cleanup. ::An example of what this would look like in the Terminal is shown here: ::[[Image:CrazyflieTerminalKeyboardInput.png|400px]] ::So you can see we commanded all 4 Crazyflies to take off (t,y,u,i), then activated Landing Mode (e), then activated Hand Mode (h), and then Ended the Program (ctrl+c). :5. End Program when finished (ctrl+c) ::This will end the program loop, print the current battery levels, and Delete the Radio pointers (shown at the end of the previous figure) ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> c716bf36d41522eff524fa871c90001cfb5bd499 134 119 2016-07-22T17:30:46Z Jnoronha 3 Added makefile section wikitext text/x-wiki The PC Client software comes in many forms. The out-of-the-box Client is written in Python and has a Graphical User Interface (GUI). The GUI is well suited for beginners, but can only support a single Radio and a single Crazyflie at a time. The easiest way to start out is with the [https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze Virtual Machine (VM)], which comes with all the files and dependencies pre-installed and can run on any computer (Windows, Mac, Linux, etc.). For more advanced users who want to use the swarm capabilities of our platform will have to use the [[#Swarm Client|Swarm Client]] we developed in C and C++. ==[https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze VM]== ('''Note:''' The VM is updated frequently so the information below may be different than the current VM) The Bitcraze wiki has a tutorial on [https://wiki.bitcraze.io/projects:virtualmachine:tutorials:vmware-win7 installing the VM]. Along with another tutorial on how to get started [https://www.bitcraze.io/getting-started-with-development/ using the VM]. These are both very simple starting guides that will help you become familiar with the VM. ===Crazyflie Client GUI=== On the VM you can find the Crazyflie Client Graphical User Interface (GUI). To run the Client you want to open a terminal and navigate to <code>projects/''''FIND PATH''''</code> and then run the command <code>sudo ./bin/cfclient</code> (Alternatively, you can use the desktop to navigate to the folder and open a terminal there) Once you do that you should see something similar to this: [[Image:DefaultCrazyflieGUIMainScreen.JPG|500px]] This is the main screen of the Client GUI and there are many tabs and features that you can access directly from this screen. The most important parts of this screen are the following: #Connect Button #Bootloader (Crazyflie Drop Down -> Bootloader) #Plotter Tab #Log Blocks Tab #Parameters Tab ====Connect Button==== This is where you will scan for Crazyflies that are powered ON. All Crazyflies not already connected will show up in the popup [[Image:DefaultCrazyflieGUIConnectScreen.JPG|400px]] We get a return that says <code>radio://0/45/2M</code>, this line is the identifier string of the Crazyflie we are trying to connect to. What this is saying is that we got a return from a Radio (Radio 0 specifically), from a Crazyflie on Channel 45 using a data rate of 2Mbps. ====Bootloader==== This where you can install new Firmware to the Crazyflie. [[Image:DefaultCrazyflieGUIBootloader.JPG|500px]] The first thing you'll need to update is to build the Firmware version you want into a .bin file. You can do this by just running the <code>make</code> command in terminal while located inside the Firmware directory you have modified. Once you have that .bin file built you: #Open the bootloader shown #Hold down the power button on the Crazyflie 2.0 for around 3 seconds until the 2 blue LED's flash and alternate. This puts the Crazyflie in bootloader mode. ('''NOTE:''' Recommend having '''ALL other Crazyflies OFF''' or else it could accidentally flash both Crazyflies.) #Then hit ''Initiate bootloader cold boot'' (it should connect to the Crazyflie in bootloader mode after a few seconds, Status will change from 'Not Connected' to 'Connected') #Hit ''Browse'' and find the .bin file you built earlier. #Then click ''Program'' and wait for the progress bar to complete. #Restart the Crazyflie in Firmware mode and make sure it starts up normally, if something seems wrong just repeat steps 2 through 6 again. ====Logging Tab==== Once you connect to a Crazyflie you can monitor certain log variables that have been set up. You will see a plot of the data similar to this: [[Image:DefaultCrazyflieGUILoggerScreen.JPG|400px]] On this screen we can do the following things: *Dropdown Menu at the top of the screen **Select which log block you want to plot on screen. *Scale the X-axis of the plot by: **Range **Number of Samples **Time in Seconds **Manually *Scale the Y-axis by: **Automatically **Manual Range ====Parameters Tab==== This tab displays all the parameters currently set up on the Crazyflie Firmware. Once you connect to a Crazyflie it lists these parameters in a table format similar to below: [[Image:DefaultCrazyflieGUIParametersScreen.JPG|400px]] For each parameter we get its Name, Variable Type, Access Type (Read/Write), and its Current Value. We can also modify the parameter values on this screen in real-time and the changes will be sent to the Crazyflie automatically. ('''Note:''' Any parameter changes made on this screen are NOT preserved when you turn OFF the Crazyflie.) ==Swarm Client== The swarm Client is a re-creation of the Original Client but programmed in C and C++. The benefit of this is that *We use a unified language between Client and Firmware *Easily migrate this platform to any linux distribution that can install the Crazyflie dependencies. **Our platform code itself requires only the VRPN libraries and a generic C compiler. ===Using the Swarm Client=== The Swarm Client uses the terminal interface for User Input. [[Image:CrazyflieTerminalInitial.png|400px]] Here we see what the initial Terminal looks like before we do anything. :1. The first thing you want to do before any testing is to run the <code>sudo make</code> command in the Swarm Client directory. (Yes, the 'sudo' is necessary) ::This will make sure you have all the necessary dependencies, that the code is error free, and then it will build an executable (.exe) file of the Swarm Client code. An error free make will look something like this: ::[[Image:CrazyflieTerminalPostMake.png|400px]] ::There will be warnings, but those don't cause any issues right now. :2. Pre-Test Checklist ::*Camera System is Turned on and Crazyflie Trackables are opened and visible. ::*Radios are plugged into the USB Ports on the Client computer. ::*Crazyflies are ON and NOT in an Error State. :3. Run the executable file using the command <code>sudo ./eris_vrpn</code> in the same directory (Yes, the 'sudo' is necessary). This will start the program initialization and a bunch of status info will flood the screen. You will know the program is ready for input when you see the following: ::[[Image:CrazyflieTerminalProgramStarted.png|400px]] ::This means that the Crazyflie yaw has been synchronized with the Camera system and they are ready to fly. :4. Input a Keyboard Command ::This will depend on what you have programmed as the keyboard input commands. As of 7/19/16 we have the following Keyboard Commands active: ::*'1' - Rotates Yaw of Crazyflie1 +45 degrees ::*'2' - Rotates Yaw of Crazyflie1 -45 degrees ::*'q' - Ends Main Loop (OBSOLETE - Replaced with ctrl + c) ::*'e' - Landing Mode (for ALL Crazyflies) ::*'t' - Crazyflie1 Take-Off ::*'y' - Crazyflie2 Take-Off ::*'u' - Crazyflie3 Take-Off ::*'i' - Crazyflie4 Take-Off ::*'h' - Hand Gesture Mode (for ALL Crazyflies) ::*'m' - Mirror Mode (for ALL Crazyflies) ::*ctrl+c - Quits Program, performs all cleanup. ::An example of what this would look like in the Terminal is shown here: ::[[Image:CrazyflieTerminalKeyboardInput.png|400px]] ::So you can see we commanded all 4 Crazyflies to take off (t,y,u,i), then activated Landing Mode (e), then activated Hand Mode (h), and then Ended the Program (ctrl+c). :5. End Program when finished (ctrl+c) ::This will end the program loop, print the current battery levels, and Delete the Radio pointers (shown at the end of the previous figure) ===Makefile=== ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> fd5faf5401083ff81eaa244fe8f4095bee974f95 USB Radio 0 6 120 57 2016-07-20T18:58:40Z Jnoronha 3 /* How does it work? */ modified directory wikitext text/x-wiki The USB Radio Dongle acts as the bridge between the Client and the Firmware. It sends control setpoints generated from the Client to the Firmware controllers, as well as receives sensor data from the Firmware to the Client for logging. == Modifying the Radio == The Radio functions can be found in the [[CCrazyRadio.cpp]] source file. === Radio Initialization === The following steps are how to Initialize a Radio. This code is currently run at the start of <code> main </code> in [[eris_vrpn.cpp]]. The process below can be extended to '''any number of Radios''' (currently 2 Radios shown) :1. Create CrazyRadio Pointers and Crazyflie Pointers <blockquote> <code> <pre> CCrazyRadio *crRadio1 = 0; CCrazyRadio *crRadio2 = 0; CCrazyflie *cflieCopter1 = 0; CCrazyflie *cflieCopter2 = 0; CCrazyflie *cflieCopter3 = 0; CCrazyflie *cflieCopter4 = 0; </pre> </code> </blockquote> '''Note:''' You must have a pointer for EACH Radio you want to initialize. :2. Initialize First CrazyRadio <blockquote> <code> <pre> crRadio1 = new CCrazyRadio(0); // dongle number (starting at 0) if( crRadio1->startRadio() ) //assigns pointer to USB location { cflieCopter1 = new CCrazyflie(crRadio1, 5); //Assigns Crazyflie1 to Radio1 on Channel 5 cflieCopter2 = new CCrazyflie(crRadio1, 80); //Assigns Crazyflie2 to Radio1 on Channel 80 } else { std::cerr << "Could not connect to dongle 1. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :3. Initialize Second CrazyRadio (repeat as necessary...) <blockquote> <code> <pre> crRadio2 = new CCrazyRadio(1); // dongle number if( crRadio2->startRadio() ) { cflieCopter3 = new CCrazyflie(crRadio2, 25); //Assigns Crazyflie3 to Radio2 on Channel 25 cflieCopter4 = new CCrazyflie(crRadio2, 45); //Assigns Crazyflie4 to Radio2 on Channel 45 } else { std::cerr << "Could not connect to dongle 2. Did you plug it in?" << std::endl; exit(-1); } usleep(10000); </pre> </code> </blockquote> :4. (OPTIONAL) Modify Radio Parameters <blockquote> <code> <pre> crRadio1->setARDTime(2000); //Sets Wait Time (in &mu;s) between Packet Retries (**MUST BE IN INCREMENTS OF 250**) crRadio1->setARC(0); //Sets Number of times Retries Packet Send crRadio1->setPower(P_0DBM); //Sets Radio Power (See CCrazyRadio.h for allowed ENUM values) </pre> </code> </blockquote> :5. '''Always''' Delete Radio Pointers Before Ending Program <blockquote> <code> <pre> delete crRadio1; delete crRadio2; </pre> </code> </blockquote> '''Note:''' If you don't delete the pointers then you need to unplug the Radio and plug it back into the USB! ====How does it work?==== The Radio initialization was originally only able to support a single Radio per computer and a single Crazyflie per Radio. This was a result of how the <code> openUSBDongle() </code> function was written. Originally the code worked as follows: [[Image:RadioSelectionOldToNew.png]] The issue with this is that if you want to assign another Radio it will always point to the same USB address, thus the different Radio pointers <code> crRadio1 </code> and <code> crRadio2 </code> would point to the same Radio dongle. So we modified the <code> openUSBDongle() </code> to take in the number of Radios you want to start, and then initialize them with a loop. === Changing Radio Channel === Changing the Radio Channel is easy, all you need to do is call the function: <blockquote> <code> <pre> crRadio1->setChannel( cflieCopter1->radioChannel() ); //Sets Radio channel to whatever value cflieCopter1 was assigned (The input can be replaced with a constant if needed) </pre> </code> </blockquote> ==== How does it work? ==== The low level implementation of the <code> setChannel </code> function looks like this: <blockquote> <code> <pre> void CCrazyRadio::setChannel(int nChannel) { if( ALL_THE_DEBUG ) printf( "%s(nChannel:%d)\n", __FUNCTION__, nChannel ); this->writeControl(NULL, 0, 0x01, nChannel, 0); } </pre> </code> </blockquote> Which is using a libusb command <code> writeControl </code> to find the specific USB address of the Radio and write a new Channel to that USB device. The specific values plugged into this function will need to be looked up if you plan on working at this level. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> d52969cee4da32fdd150f792c8e70b2fce9fae73 Controller 0 5 122 72 2016-07-20T18:59:24Z Jnoronha 3 /* Calculating the PID's */ modified directory wikitext text/x-wiki The Crazyflie platform is completely customizable when it comes to the control design. As long as the controller can be written in C or C++, we can implement it in the Platform. This applies to both the controllers run on the PC Client and the controllers run on the Firmware of the Crazyflie. Originally the only controllers in the Platform were Firmware PID's that controlled the angular position and rates of the Crazyflie for hand flight. The original controller layout can be seen here [[#Original PID Controllers (Angular Rotation)|Original PID's]]. Below you will find documentation on the different types of Controllers that have been applied to the platform, organized by their location in the Platform. == Firmware == === Original PID Controllers (Angular Rotation) === Directly on the Crazyflie Firmware there are 5 PID controllers as seen here: [[Image:FirmwareOnlyPIDArchitecture.png|500px]] The Pitch and Roll angular position PID's receive constant setpoints from some outside source (gamepad controller or automated controller). The outputs of those angular position controllers is then fed into the angular rate controllers as shown. This final output is then fed into the Motor Command block which converts the angular rate setpoints into motor commands. ---- ===State Estimator (Not Implemented Yet)=== ('''***NOT YET IMPLEMENTED***''') Bitcraze is currently working on adding a state estimator onto the Firmware to handle control calculations instead of the PID. The code is in place but the controller is not yet used as of '''7/13/16'''. == PC Client == === PID Controllers (Position and Yaw) === The first controller implemented on the Client were 4 PID controllers used to stabilize the Crazyflie's position in X, Y, and Z, and angular position in Yaw respectively. These PID's feed directly into the Firmware PID's as seen here: [[Image:CompletePIDArchitectureFigure.png|500px]] The controllers inside the red box are the original PID controllers located on the Firmware as shown above in the [[#Original PID Controllers (Angular Rotation)|Original PID's]]. ====Initialize the PID's==== :1. To start we create a struct with all the necessary variables (code from ''pid.h''): <blockquote> <code> <pre> typedef struct { float desired; //< set point float error; //< error float prevError; //< previous error float integ; //< integral float deriv; //< derivative float kp; //< proportional gain float ki; //< integral gain float kd; //< derivative gain float outP; //< proportional output (debugging) float outI; //< integral output (debugging) float outD; //< derivative output (debugging) float iLimit; //< integral limit float iLimitLow; //< integral limit float dt; //< delta-time dt float angularLimit; //sets limit for how far Crazyflie can tip, to prevent flipping float angularLimitLow; //^ float thrustLimit; //Sets upper limit for Thrust Output (60000?) **? float thrustLimitLow; //Sets lower limit for thrust Output (10001) } PidObject; </pre> </code> </blockquote> :2. To simplify scaling up the code to multiple Crazyflies, we will create a <code> ControllerObject </code> that contains multiple PID structs as shown (code in ''controller.h''): <blockquote> <code> <pre> typedef struct { PidObject pidRoll; PidObject pidPitch; PidObject pidYaw; PidObject pidX; PidObject pidY; PidObject pidZ; bool isInit; } ControllerObject; </pre> </code> </blockquote> :3. Then we initialize the Objects to 0 at the start of each run (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> ControllerObject pidCtrl1 = { 0 }; // init all fields to zero ControllerObject pidCtrl2 = { 0 }; // init all fields to zero ControllerObject pidCtrl3 = { 0 }; // init all fields to zero ControllerObject pidCtrl4 = { 0 }; // init all fields to zero </pre> </code> </blockquote> :4. Then populate the PidObjects with the desired parameters (code in ''pid.c''): <blockquote> <code> <pre> void pidInit(PidObject* pid, const float desired, const float kp, const float ki, const float kd, const float dt) { pid->error = 0; pid->prevError = 0; pid->integ = 0; pid->deriv = 0; pid->desired = desired; pid->kp = kp; pid->ki = ki; pid->kd = kd; pid->iLimit = DEFAULT_PID_INTEGRATION_LIMIT; pid->iLimitLow = -DEFAULT_PID_INTEGRATION_LIMIT; pid->angularLimit = DEFAULT_PID_ANGLE_OUTPUT; pid->angularLimitLow = -DEFAULT_PID_ANGLE_OUTPUT; pid->thrustLimit = DEFAULT_PID_HIGH_THRUST_LIMIT; pid->thrustLimitLow = DEFAULT_PID_LOW_THRUST_LIMIT; pid->dt = dt; } </pre> </code> </blockquote> Using the above function for each of the <code>PidObjects</code> inside of the <code>ControllerObject</code> below (code in ''controller.c''): <blockquote> <code> <pre> void controllerInit( ControllerObject * ctrl ) { if(ctrl->isInit) return; pidInit(&ctrl->pidY, 0, PID_Y_KP, PID_Y_KI, PID_Y_KD, CAMERA_UPDATE_DT); //for Roll PID pidInit(&ctrl->pidX, 0, PID_X_KP, PID_X_KI, PID_X_KD, CAMERA_UPDATE_DT); //for Pitch PID pidInit(&ctrl->pidYaw, 0, PID_YAW_KP, PID_YAW_KI, PID_YAW_KD, CAMERA_UPDATE_DT); pidInit(&ctrl->pidZ, 0, PID_Z_KP, PID_Z_KI, PID_Z_KD, CAMERA_UPDATE_DT); pidSetIntegralLimit(&ctrl->pidY, PID_Y_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidX, PID_X_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidYaw, PID_YAW_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidZ, PID_Z_INTEGRATION_LIMIT); ctrl->isInit = true; } </pre> </code> </blockquote> '''Note:''' If we have multiple Crazyflies we need a <code>ControllerObject</code> for each Crazyflie (code in ''eris_vrpn.cpp'') <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl1 ); controllerInit( &pidCtrl1 ); #endif #if NUM_QUADS >= 2 controllerResetAllPID( &pidCtrl2 ); controllerInit( &pidCtrl2 ); #endif #if NUM_QUADS >=3 controllerResetAllPID( &pidCtrl3 ); controllerInit( &pidCtrl3 ); #endif #if NUM_QUADS >=4 controllerResetAllPID( &pidCtrl4 ); controllerInit( &pidCtrl4 ); #endif </pre> </code> </blockquote> Now the initialization of the Controllers is complete. ====Calculating the PID's==== :1. Each loop we want to calculate the PID output (code in ''pid.c''): <blockquote> <code> <pre> float pidUpdateAngle(PidObject* pid, const float measured, const bool updateError) //**USED FOR ATTITUDE CONTROL { float output; if(updateError) { pid->error = pid->desired - measured; //Calculates current error } pid->integ += pid->error * pid->dt; //Calculates integral term if(pid->integ > pid->iLimit) //Checks that the integral term stays below the integral limit (anti-windup) { pid->integ = pid->iLimit; } else if(pid->integ < pid->iLimitLow) { pid->integ = pid->iLimitLow; } pid->deriv = (pid->error - pid->prevError) / pid->dt; //Calculates derivative term pid->outP = pid->kp* pid->error; pid->outI = pid->ki * pid->integ; pid->outD = pid->kd * pid->deriv; output = pid->outP + pid->outI + pid->outD; //Adds up all 3 calculated terms for output if(output > pid->angularLimit) //Limits amount Crazyflie can tip { output = pid->angularLimit; } if(output < pid->angularLimitLow) //Limits amount Crazyflie can tip { output = pid->angularLimitLow; } pid->prevError = pid->error; //Stores the current error for next loop return output; } </pre> </code> </blockquote> '''Note:''' There are 3 different versions of this Function (for Angle, Thrust, and Yaw) since each has different output limits. :2. Using the function above, combine all PID calculations into one function (code in ''controller.c''): <blockquote> <code> <pre> void controllerCorrectAttitudePID(ControllerObject * ctrl, float xPositionActual, float yPositionActual, float zPositionActual, float eulerYawActual, float xPositionDesired, float yPositionDesired, float zPositionDesired, float eulerYawDesired, float* rollControlOutput, float* pitchControlOutput, float* yawControlOutput, float* thrustControlOutput) { pidSetDesired(&ctrl->pidX, xPositionDesired); *pitchControlOutput = pidUpdateAngle(&ctrl->pidX, xPositionActual, false); //Originally true pidSetDesired(&ctrl->pidY, yPositionDesired); *rollControlOutput = pidUpdateAngle(&ctrl->pidY, yPositionActual, false); //Originally true pidSetDesired(&ctrl->pidZ, zPositionDesired); *thrustControlOutput = pidUpdateThrust(&ctrl->pidZ,zPositionActual, true); float yawError; pidSetDesired(&ctrl->pidYaw, eulerYawDesired); yawError = eulerYawDesired - eulerYawActual; if(yawError > 180.0) //Ensures Yaw error stays between -180 and 180 degrees yawError -= 360.0; else if(yawError < -180.0) yawError += 360.0; pidSetError(&ctrl->pidYaw, yawError); *yawControlOutput = pidUpdateYaw(&ctrl->pidYaw, eulerYawActual, true); //originally false } </pre> </code> </blockquote> :3. In each Callback, calculate the Controller outputs, assigned to pointer values<code>*rollControlOutput</code>, <code>*pitchControlOutput</code>, etc... (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; //Calculates error externally controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); </pre> </code> </blockquote> '''Note:''' We calculate error externally for X and Y because certain swarm controllers need special setpoint modifiers (this way we can switch modes without effecting the default setpoint): '''Example:''' Follow Hand Mode Error (Crazyflie1 will have setpoint -0.5 m lower in X and +0.5 m higher in Y than your hand trackable): <blockquote> <code> <pre> ... xError1 = (xPositionHand - 0.5) - xPosition1; yError1 = (yPositionHand + 0.5) - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); ... </pre> </code> </blockquote> :4. Repeat for each set of new location data... ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 8f3235d5554038d328eb6f8c86fe60119e97b130 131 122 2016-07-21T18:53:43Z Jnoronha 3 /* Calculating the PID's */ formatting tabs wikitext text/x-wiki The Crazyflie platform is completely customizable when it comes to the control design. As long as the controller can be written in C or C++, we can implement it in the Platform. This applies to both the controllers run on the PC Client and the controllers run on the Firmware of the Crazyflie. Originally the only controllers in the Platform were Firmware PID's that controlled the angular position and rates of the Crazyflie for hand flight. The original controller layout can be seen here [[#Original PID Controllers (Angular Rotation)|Original PID's]]. Below you will find documentation on the different types of Controllers that have been applied to the platform, organized by their location in the Platform. == Firmware == === Original PID Controllers (Angular Rotation) === Directly on the Crazyflie Firmware there are 5 PID controllers as seen here: [[Image:FirmwareOnlyPIDArchitecture.png|500px]] The Pitch and Roll angular position PID's receive constant setpoints from some outside source (gamepad controller or automated controller). The outputs of those angular position controllers is then fed into the angular rate controllers as shown. This final output is then fed into the Motor Command block which converts the angular rate setpoints into motor commands. ---- ===State Estimator (Not Implemented Yet)=== ('''***NOT YET IMPLEMENTED***''') Bitcraze is currently working on adding a state estimator onto the Firmware to handle control calculations instead of the PID. The code is in place but the controller is not yet used as of '''7/13/16'''. == PC Client == === PID Controllers (Position and Yaw) === The first controller implemented on the Client were 4 PID controllers used to stabilize the Crazyflie's position in X, Y, and Z, and angular position in Yaw respectively. These PID's feed directly into the Firmware PID's as seen here: [[Image:CompletePIDArchitectureFigure.png|500px]] The controllers inside the red box are the original PID controllers located on the Firmware as shown above in the [[#Original PID Controllers (Angular Rotation)|Original PID's]]. ====Initialize the PID's==== :1. To start we create a struct with all the necessary variables (code from ''pid.h''): <blockquote> <code> <pre> typedef struct { float desired; //< set point float error; //< error float prevError; //< previous error float integ; //< integral float deriv; //< derivative float kp; //< proportional gain float ki; //< integral gain float kd; //< derivative gain float outP; //< proportional output (debugging) float outI; //< integral output (debugging) float outD; //< derivative output (debugging) float iLimit; //< integral limit float iLimitLow; //< integral limit float dt; //< delta-time dt float angularLimit; //sets limit for how far Crazyflie can tip, to prevent flipping float angularLimitLow; //^ float thrustLimit; //Sets upper limit for Thrust Output (60000?) **? float thrustLimitLow; //Sets lower limit for thrust Output (10001) } PidObject; </pre> </code> </blockquote> :2. To simplify scaling up the code to multiple Crazyflies, we will create a <code> ControllerObject </code> that contains multiple PID structs as shown (code in ''controller.h''): <blockquote> <code> <pre> typedef struct { PidObject pidRoll; PidObject pidPitch; PidObject pidYaw; PidObject pidX; PidObject pidY; PidObject pidZ; bool isInit; } ControllerObject; </pre> </code> </blockquote> :3. Then we initialize the Objects to 0 at the start of each run (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> ControllerObject pidCtrl1 = { 0 }; // init all fields to zero ControllerObject pidCtrl2 = { 0 }; // init all fields to zero ControllerObject pidCtrl3 = { 0 }; // init all fields to zero ControllerObject pidCtrl4 = { 0 }; // init all fields to zero </pre> </code> </blockquote> :4. Then populate the PidObjects with the desired parameters (code in ''pid.c''): <blockquote> <code> <pre> void pidInit(PidObject* pid, const float desired, const float kp, const float ki, const float kd, const float dt) { pid->error = 0; pid->prevError = 0; pid->integ = 0; pid->deriv = 0; pid->desired = desired; pid->kp = kp; pid->ki = ki; pid->kd = kd; pid->iLimit = DEFAULT_PID_INTEGRATION_LIMIT; pid->iLimitLow = -DEFAULT_PID_INTEGRATION_LIMIT; pid->angularLimit = DEFAULT_PID_ANGLE_OUTPUT; pid->angularLimitLow = -DEFAULT_PID_ANGLE_OUTPUT; pid->thrustLimit = DEFAULT_PID_HIGH_THRUST_LIMIT; pid->thrustLimitLow = DEFAULT_PID_LOW_THRUST_LIMIT; pid->dt = dt; } </pre> </code> </blockquote> Using the above function for each of the <code>PidObjects</code> inside of the <code>ControllerObject</code> below (code in ''controller.c''): <blockquote> <code> <pre> void controllerInit( ControllerObject * ctrl ) { if(ctrl->isInit) return; pidInit(&ctrl->pidY, 0, PID_Y_KP, PID_Y_KI, PID_Y_KD, CAMERA_UPDATE_DT); //for Roll PID pidInit(&ctrl->pidX, 0, PID_X_KP, PID_X_KI, PID_X_KD, CAMERA_UPDATE_DT); //for Pitch PID pidInit(&ctrl->pidYaw, 0, PID_YAW_KP, PID_YAW_KI, PID_YAW_KD, CAMERA_UPDATE_DT); pidInit(&ctrl->pidZ, 0, PID_Z_KP, PID_Z_KI, PID_Z_KD, CAMERA_UPDATE_DT); pidSetIntegralLimit(&ctrl->pidY, PID_Y_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidX, PID_X_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidYaw, PID_YAW_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidZ, PID_Z_INTEGRATION_LIMIT); ctrl->isInit = true; } </pre> </code> </blockquote> '''Note:''' If we have multiple Crazyflies we need a <code>ControllerObject</code> for each Crazyflie (code in ''eris_vrpn.cpp'') <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl1 ); controllerInit( &pidCtrl1 ); #endif #if NUM_QUADS >= 2 controllerResetAllPID( &pidCtrl2 ); controllerInit( &pidCtrl2 ); #endif #if NUM_QUADS >=3 controllerResetAllPID( &pidCtrl3 ); controllerInit( &pidCtrl3 ); #endif #if NUM_QUADS >=4 controllerResetAllPID( &pidCtrl4 ); controllerInit( &pidCtrl4 ); #endif </pre> </code> </blockquote> Now the initialization of the Controllers is complete. ====Calculating the PID's==== :1. Each loop we want to calculate the PID output (code in ''pid.c''): <blockquote> <code> <pre> float pidUpdateAngle(PidObject* pid, const float measured, const bool updateError) //**USED FOR ATTITUDE CONTROL { float output; if(updateError) { pid->error = pid->desired - measured; //Calculates current error } pid->integ += pid->error * pid->dt; //Calculates integral term if(pid->integ > pid->iLimit) //Checks that the integral term stays below the integral limit (anti-windup) { pid->integ = pid->iLimit; } else if(pid->integ < pid->iLimitLow) { pid->integ = pid->iLimitLow; } pid->deriv = (pid->error - pid->prevError) / pid->dt; //Calculates derivative term pid->outP = pid->kp* pid->error; pid->outI = pid->ki * pid->integ; pid->outD = pid->kd * pid->deriv; output = pid->outP + pid->outI + pid->outD; //Adds up all 3 calculated terms for output if(output > pid->angularLimit) //Limits amount Crazyflie can tip { output = pid->angularLimit; } if(output < pid->angularLimitLow) //Limits amount Crazyflie can tip { output = pid->angularLimitLow; } pid->prevError = pid->error; //Stores the current error for next loop return output; } </pre> </code> </blockquote> ::'''Note:''' There are 3 different versions of this Function (for Angle, Thrust, and Yaw) since each has different output limits. :2. Using the function above, combine all PID calculations into one function (code in ''controller.c''): <blockquote> <code> <pre> void controllerCorrectAttitudePID(ControllerObject * ctrl, float xPositionActual, float yPositionActual, float zPositionActual, float eulerYawActual, float xPositionDesired, float yPositionDesired, float zPositionDesired, float eulerYawDesired, float* rollControlOutput, float* pitchControlOutput, float* yawControlOutput, float* thrustControlOutput) { pidSetDesired(&ctrl->pidX, xPositionDesired); *pitchControlOutput = pidUpdateAngle(&ctrl->pidX, xPositionActual, false); //Originally true pidSetDesired(&ctrl->pidY, yPositionDesired); *rollControlOutput = pidUpdateAngle(&ctrl->pidY, yPositionActual, false); //Originally true pidSetDesired(&ctrl->pidZ, zPositionDesired); *thrustControlOutput = pidUpdateThrust(&ctrl->pidZ,zPositionActual, true); float yawError; pidSetDesired(&ctrl->pidYaw, eulerYawDesired); yawError = eulerYawDesired - eulerYawActual; if(yawError > 180.0) //Ensures Yaw error stays between -180 and 180 degrees yawError -= 360.0; else if(yawError < -180.0) yawError += 360.0; pidSetError(&ctrl->pidYaw, yawError); *yawControlOutput = pidUpdateYaw(&ctrl->pidYaw, eulerYawActual, true); //originally false } </pre> </code> </blockquote> :3. In each Callback, calculate the Controller outputs, assigned to pointer values<code>*rollControlOutput</code>, <code>*pitchControlOutput</code>, etc... (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; //Calculates error externally controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); </pre> </code> </blockquote> ::'''Note:''' We calculate error externally for X and Y because certain swarm controllers need special setpoint modifiers (this way we can switch modes without effecting the default setpoint): ::'''Example:''' Follow Hand Mode Error (Crazyflie1 will have setpoint -0.5 m lower in X and +0.5 m higher in Y than your hand trackable): <blockquote> <code> <pre> ... xError1 = (xPositionHand - 0.5) - xPosition1; yError1 = (yPositionHand + 0.5) - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); ... </pre> </code> </blockquote> :4. Repeat for each set of new location data...until Program END. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 6f011366331e5775b63fa07627dbb38ea4bdca46 132 131 2016-07-21T18:54:23Z Jnoronha 3 /* PID Controllers (Position and Yaw) */ changed heading to specify Client wikitext text/x-wiki The Crazyflie platform is completely customizable when it comes to the control design. As long as the controller can be written in C or C++, we can implement it in the Platform. This applies to both the controllers run on the PC Client and the controllers run on the Firmware of the Crazyflie. Originally the only controllers in the Platform were Firmware PID's that controlled the angular position and rates of the Crazyflie for hand flight. The original controller layout can be seen here [[#Original PID Controllers (Angular Rotation)|Original PID's]]. Below you will find documentation on the different types of Controllers that have been applied to the platform, organized by their location in the Platform. == Firmware == === Original PID Controllers (Angular Rotation) === Directly on the Crazyflie Firmware there are 5 PID controllers as seen here: [[Image:FirmwareOnlyPIDArchitecture.png|500px]] The Pitch and Roll angular position PID's receive constant setpoints from some outside source (gamepad controller or automated controller). The outputs of those angular position controllers is then fed into the angular rate controllers as shown. This final output is then fed into the Motor Command block which converts the angular rate setpoints into motor commands. ---- ===State Estimator (Not Implemented Yet)=== ('''***NOT YET IMPLEMENTED***''') Bitcraze is currently working on adding a state estimator onto the Firmware to handle control calculations instead of the PID. The code is in place but the controller is not yet used as of '''7/13/16'''. == PC Client == === Client PID Controllers (Position and Yaw) === The first controller implemented on the Client were 4 PID controllers used to stabilize the Crazyflie's position in X, Y, and Z, and angular position in Yaw respectively. These PID's feed directly into the Firmware PID's as seen here: [[Image:CompletePIDArchitectureFigure.png|500px]] The controllers inside the red box are the original PID controllers located on the Firmware as shown above in the [[#Original PID Controllers (Angular Rotation)|Original PID's]]. ====Initialize the PID's==== :1. To start we create a struct with all the necessary variables (code from ''pid.h''): <blockquote> <code> <pre> typedef struct { float desired; //< set point float error; //< error float prevError; //< previous error float integ; //< integral float deriv; //< derivative float kp; //< proportional gain float ki; //< integral gain float kd; //< derivative gain float outP; //< proportional output (debugging) float outI; //< integral output (debugging) float outD; //< derivative output (debugging) float iLimit; //< integral limit float iLimitLow; //< integral limit float dt; //< delta-time dt float angularLimit; //sets limit for how far Crazyflie can tip, to prevent flipping float angularLimitLow; //^ float thrustLimit; //Sets upper limit for Thrust Output (60000?) **? float thrustLimitLow; //Sets lower limit for thrust Output (10001) } PidObject; </pre> </code> </blockquote> :2. To simplify scaling up the code to multiple Crazyflies, we will create a <code> ControllerObject </code> that contains multiple PID structs as shown (code in ''controller.h''): <blockquote> <code> <pre> typedef struct { PidObject pidRoll; PidObject pidPitch; PidObject pidYaw; PidObject pidX; PidObject pidY; PidObject pidZ; bool isInit; } ControllerObject; </pre> </code> </blockquote> :3. Then we initialize the Objects to 0 at the start of each run (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> ControllerObject pidCtrl1 = { 0 }; // init all fields to zero ControllerObject pidCtrl2 = { 0 }; // init all fields to zero ControllerObject pidCtrl3 = { 0 }; // init all fields to zero ControllerObject pidCtrl4 = { 0 }; // init all fields to zero </pre> </code> </blockquote> :4. Then populate the PidObjects with the desired parameters (code in ''pid.c''): <blockquote> <code> <pre> void pidInit(PidObject* pid, const float desired, const float kp, const float ki, const float kd, const float dt) { pid->error = 0; pid->prevError = 0; pid->integ = 0; pid->deriv = 0; pid->desired = desired; pid->kp = kp; pid->ki = ki; pid->kd = kd; pid->iLimit = DEFAULT_PID_INTEGRATION_LIMIT; pid->iLimitLow = -DEFAULT_PID_INTEGRATION_LIMIT; pid->angularLimit = DEFAULT_PID_ANGLE_OUTPUT; pid->angularLimitLow = -DEFAULT_PID_ANGLE_OUTPUT; pid->thrustLimit = DEFAULT_PID_HIGH_THRUST_LIMIT; pid->thrustLimitLow = DEFAULT_PID_LOW_THRUST_LIMIT; pid->dt = dt; } </pre> </code> </blockquote> Using the above function for each of the <code>PidObjects</code> inside of the <code>ControllerObject</code> below (code in ''controller.c''): <blockquote> <code> <pre> void controllerInit( ControllerObject * ctrl ) { if(ctrl->isInit) return; pidInit(&ctrl->pidY, 0, PID_Y_KP, PID_Y_KI, PID_Y_KD, CAMERA_UPDATE_DT); //for Roll PID pidInit(&ctrl->pidX, 0, PID_X_KP, PID_X_KI, PID_X_KD, CAMERA_UPDATE_DT); //for Pitch PID pidInit(&ctrl->pidYaw, 0, PID_YAW_KP, PID_YAW_KI, PID_YAW_KD, CAMERA_UPDATE_DT); pidInit(&ctrl->pidZ, 0, PID_Z_KP, PID_Z_KI, PID_Z_KD, CAMERA_UPDATE_DT); pidSetIntegralLimit(&ctrl->pidY, PID_Y_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidX, PID_X_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidYaw, PID_YAW_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidZ, PID_Z_INTEGRATION_LIMIT); ctrl->isInit = true; } </pre> </code> </blockquote> '''Note:''' If we have multiple Crazyflies we need a <code>ControllerObject</code> for each Crazyflie (code in ''eris_vrpn.cpp'') <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl1 ); controllerInit( &pidCtrl1 ); #endif #if NUM_QUADS >= 2 controllerResetAllPID( &pidCtrl2 ); controllerInit( &pidCtrl2 ); #endif #if NUM_QUADS >=3 controllerResetAllPID( &pidCtrl3 ); controllerInit( &pidCtrl3 ); #endif #if NUM_QUADS >=4 controllerResetAllPID( &pidCtrl4 ); controllerInit( &pidCtrl4 ); #endif </pre> </code> </blockquote> Now the initialization of the Controllers is complete. ====Calculating the PID's==== :1. Each loop we want to calculate the PID output (code in ''pid.c''): <blockquote> <code> <pre> float pidUpdateAngle(PidObject* pid, const float measured, const bool updateError) //**USED FOR ATTITUDE CONTROL { float output; if(updateError) { pid->error = pid->desired - measured; //Calculates current error } pid->integ += pid->error * pid->dt; //Calculates integral term if(pid->integ > pid->iLimit) //Checks that the integral term stays below the integral limit (anti-windup) { pid->integ = pid->iLimit; } else if(pid->integ < pid->iLimitLow) { pid->integ = pid->iLimitLow; } pid->deriv = (pid->error - pid->prevError) / pid->dt; //Calculates derivative term pid->outP = pid->kp* pid->error; pid->outI = pid->ki * pid->integ; pid->outD = pid->kd * pid->deriv; output = pid->outP + pid->outI + pid->outD; //Adds up all 3 calculated terms for output if(output > pid->angularLimit) //Limits amount Crazyflie can tip { output = pid->angularLimit; } if(output < pid->angularLimitLow) //Limits amount Crazyflie can tip { output = pid->angularLimitLow; } pid->prevError = pid->error; //Stores the current error for next loop return output; } </pre> </code> </blockquote> ::'''Note:''' There are 3 different versions of this Function (for Angle, Thrust, and Yaw) since each has different output limits. :2. Using the function above, combine all PID calculations into one function (code in ''controller.c''): <blockquote> <code> <pre> void controllerCorrectAttitudePID(ControllerObject * ctrl, float xPositionActual, float yPositionActual, float zPositionActual, float eulerYawActual, float xPositionDesired, float yPositionDesired, float zPositionDesired, float eulerYawDesired, float* rollControlOutput, float* pitchControlOutput, float* yawControlOutput, float* thrustControlOutput) { pidSetDesired(&ctrl->pidX, xPositionDesired); *pitchControlOutput = pidUpdateAngle(&ctrl->pidX, xPositionActual, false); //Originally true pidSetDesired(&ctrl->pidY, yPositionDesired); *rollControlOutput = pidUpdateAngle(&ctrl->pidY, yPositionActual, false); //Originally true pidSetDesired(&ctrl->pidZ, zPositionDesired); *thrustControlOutput = pidUpdateThrust(&ctrl->pidZ,zPositionActual, true); float yawError; pidSetDesired(&ctrl->pidYaw, eulerYawDesired); yawError = eulerYawDesired - eulerYawActual; if(yawError > 180.0) //Ensures Yaw error stays between -180 and 180 degrees yawError -= 360.0; else if(yawError < -180.0) yawError += 360.0; pidSetError(&ctrl->pidYaw, yawError); *yawControlOutput = pidUpdateYaw(&ctrl->pidYaw, eulerYawActual, true); //originally false } </pre> </code> </blockquote> :3. In each Callback, calculate the Controller outputs, assigned to pointer values<code>*rollControlOutput</code>, <code>*pitchControlOutput</code>, etc... (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; //Calculates error externally controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); </pre> </code> </blockquote> ::'''Note:''' We calculate error externally for X and Y because certain swarm controllers need special setpoint modifiers (this way we can switch modes without effecting the default setpoint): ::'''Example:''' Follow Hand Mode Error (Crazyflie1 will have setpoint -0.5 m lower in X and +0.5 m higher in Y than your hand trackable): <blockquote> <code> <pre> ... xError1 = (xPositionHand - 0.5) - xPosition1; yError1 = (yPositionHand + 0.5) - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); ... </pre> </code> </blockquote> :4. Repeat for each set of new location data...until Program END. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> ca838e1358b4d3a7ec439457c0424ef221297ac6 133 132 2016-07-21T19:32:04Z Jnoronha 3 /* PC Client */ added sending calculated setpoints over the radio code wikitext text/x-wiki The Crazyflie platform is completely customizable when it comes to the control design. As long as the controller can be written in C or C++, we can implement it in the Platform. This applies to both the controllers run on the PC Client and the controllers run on the Firmware of the Crazyflie. Originally the only controllers in the Platform were Firmware PID's that controlled the angular position and rates of the Crazyflie for hand flight. The original controller layout can be seen here [[#Original PID Controllers (Angular Rotation)|Original PID's]]. Below you will find documentation on the different types of Controllers that have been applied to the platform, organized by their location in the Platform. == Firmware == === Original PID Controllers (Angular Rotation) === Directly on the Crazyflie Firmware there are 5 PID controllers as seen here: [[Image:FirmwareOnlyPIDArchitecture.png|500px]] The Pitch and Roll angular position PID's receive constant setpoints from some outside source (gamepad controller or automated controller). The outputs of those angular position controllers is then fed into the angular rate controllers as shown. This final output is then fed into the Motor Command block which converts the angular rate setpoints into motor commands. ---- ===State Estimator (Not Implemented Yet)=== ('''***NOT YET IMPLEMENTED***''') Bitcraze is currently working on adding a state estimator onto the Firmware to handle control calculations instead of the PID. The code is in place but the controller is not yet used as of '''7/13/16'''. == PC Client == === Client PID Controllers (Position and Yaw) === The first controller implemented on the Client were 4 PID controllers used to stabilize the Crazyflie's position in X, Y, and Z, and angular position in Yaw respectively. These PID's feed directly into the Firmware PID's as seen here: [[Image:CompletePIDArchitectureFigure.png|500px]] The controllers inside the red box are the original PID controllers located on the Firmware as shown above in the [[#Original PID Controllers (Angular Rotation)|Original PID's]]. ====Initialize the PID's==== :1. To start we create a struct with all the necessary variables (code from ''pid.h''): <blockquote> <code> <pre> typedef struct { float desired; //< set point float error; //< error float prevError; //< previous error float integ; //< integral float deriv; //< derivative float kp; //< proportional gain float ki; //< integral gain float kd; //< derivative gain float outP; //< proportional output (debugging) float outI; //< integral output (debugging) float outD; //< derivative output (debugging) float iLimit; //< integral limit float iLimitLow; //< integral limit float dt; //< delta-time dt float angularLimit; //sets limit for how far Crazyflie can tip, to prevent flipping float angularLimitLow; //^ float thrustLimit; //Sets upper limit for Thrust Output (60000?) **? float thrustLimitLow; //Sets lower limit for thrust Output (10001) } PidObject; </pre> </code> </blockquote> :2. To simplify scaling up the code to multiple Crazyflies, we will create a <code> ControllerObject </code> that contains multiple PID structs as shown (code in ''controller.h''): <blockquote> <code> <pre> typedef struct { PidObject pidRoll; PidObject pidPitch; PidObject pidYaw; PidObject pidX; PidObject pidY; PidObject pidZ; bool isInit; } ControllerObject; </pre> </code> </blockquote> :3. Then we initialize the Objects to 0 at the start of each run (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> ControllerObject pidCtrl1 = { 0 }; // init all fields to zero ControllerObject pidCtrl2 = { 0 }; // init all fields to zero ControllerObject pidCtrl3 = { 0 }; // init all fields to zero ControllerObject pidCtrl4 = { 0 }; // init all fields to zero </pre> </code> </blockquote> :4. Then populate the PidObjects with the desired parameters (code in ''pid.c''): <blockquote> <code> <pre> void pidInit(PidObject* pid, const float desired, const float kp, const float ki, const float kd, const float dt) { pid->error = 0; pid->prevError = 0; pid->integ = 0; pid->deriv = 0; pid->desired = desired; pid->kp = kp; pid->ki = ki; pid->kd = kd; pid->iLimit = DEFAULT_PID_INTEGRATION_LIMIT; pid->iLimitLow = -DEFAULT_PID_INTEGRATION_LIMIT; pid->angularLimit = DEFAULT_PID_ANGLE_OUTPUT; pid->angularLimitLow = -DEFAULT_PID_ANGLE_OUTPUT; pid->thrustLimit = DEFAULT_PID_HIGH_THRUST_LIMIT; pid->thrustLimitLow = DEFAULT_PID_LOW_THRUST_LIMIT; pid->dt = dt; } </pre> </code> </blockquote> Using the above function for each of the <code>PidObjects</code> inside of the <code>ControllerObject</code> below (code in ''controller.c''): <blockquote> <code> <pre> void controllerInit( ControllerObject * ctrl ) { if(ctrl->isInit) return; pidInit(&ctrl->pidY, 0, PID_Y_KP, PID_Y_KI, PID_Y_KD, CAMERA_UPDATE_DT); //for Roll PID pidInit(&ctrl->pidX, 0, PID_X_KP, PID_X_KI, PID_X_KD, CAMERA_UPDATE_DT); //for Pitch PID pidInit(&ctrl->pidYaw, 0, PID_YAW_KP, PID_YAW_KI, PID_YAW_KD, CAMERA_UPDATE_DT); pidInit(&ctrl->pidZ, 0, PID_Z_KP, PID_Z_KI, PID_Z_KD, CAMERA_UPDATE_DT); pidSetIntegralLimit(&ctrl->pidY, PID_Y_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidX, PID_X_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidYaw, PID_YAW_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidZ, PID_Z_INTEGRATION_LIMIT); ctrl->isInit = true; } </pre> </code> </blockquote> '''Note:''' If we have multiple Crazyflies we need a <code>ControllerObject</code> for each Crazyflie (code in ''eris_vrpn.cpp'') <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl1 ); controllerInit( &pidCtrl1 ); #endif #if NUM_QUADS >= 2 controllerResetAllPID( &pidCtrl2 ); controllerInit( &pidCtrl2 ); #endif #if NUM_QUADS >=3 controllerResetAllPID( &pidCtrl3 ); controllerInit( &pidCtrl3 ); #endif #if NUM_QUADS >=4 controllerResetAllPID( &pidCtrl4 ); controllerInit( &pidCtrl4 ); #endif </pre> </code> </blockquote> Now the initialization of the Controllers is complete. ====Calculating the PID's==== :1. Each loop we want to calculate the PID output (code in ''pid.c''): <blockquote> <code> <pre> float pidUpdateAngle(PidObject* pid, const float measured, const bool updateError) //**USED FOR ATTITUDE CONTROL { float output; if(updateError) { pid->error = pid->desired - measured; //Calculates current error } pid->integ += pid->error * pid->dt; //Calculates integral term if(pid->integ > pid->iLimit) //Checks that the integral term stays below the integral limit (anti-windup) { pid->integ = pid->iLimit; } else if(pid->integ < pid->iLimitLow) { pid->integ = pid->iLimitLow; } pid->deriv = (pid->error - pid->prevError) / pid->dt; //Calculates derivative term pid->outP = pid->kp* pid->error; pid->outI = pid->ki * pid->integ; pid->outD = pid->kd * pid->deriv; output = pid->outP + pid->outI + pid->outD; //Adds up all 3 calculated terms for output if(output > pid->angularLimit) //Limits amount Crazyflie can tip { output = pid->angularLimit; } if(output < pid->angularLimitLow) //Limits amount Crazyflie can tip { output = pid->angularLimitLow; } pid->prevError = pid->error; //Stores the current error for next loop return output; } </pre> </code> </blockquote> ::'''Note:''' There are 3 different versions of this Function (for Angle, Thrust, and Yaw) since each has different output limits. :2. Using the function above, combine all PID calculations into one function (code in ''controller.c''): <blockquote> <code> <pre> void controllerCorrectAttitudePID(ControllerObject * ctrl, float xPositionActual, float yPositionActual, float zPositionActual, float eulerYawActual, float xPositionDesired, float yPositionDesired, float zPositionDesired, float eulerYawDesired, float* rollControlOutput, float* pitchControlOutput, float* yawControlOutput, float* thrustControlOutput) { pidSetDesired(&ctrl->pidX, xPositionDesired); *pitchControlOutput = pidUpdateAngle(&ctrl->pidX, xPositionActual, false); //Originally true pidSetDesired(&ctrl->pidY, yPositionDesired); *rollControlOutput = pidUpdateAngle(&ctrl->pidY, yPositionActual, false); //Originally true pidSetDesired(&ctrl->pidZ, zPositionDesired); *thrustControlOutput = pidUpdateThrust(&ctrl->pidZ,zPositionActual, true); float yawError; pidSetDesired(&ctrl->pidYaw, eulerYawDesired); yawError = eulerYawDesired - eulerYawActual; if(yawError > 180.0) //Ensures Yaw error stays between -180 and 180 degrees yawError -= 360.0; else if(yawError < -180.0) yawError += 360.0; pidSetError(&ctrl->pidYaw, yawError); *yawControlOutput = pidUpdateYaw(&ctrl->pidYaw, eulerYawActual, true); //originally false } </pre> </code> </blockquote> :3. In each Callback, calculate the Controller outputs, assigned to pointer values <code>*rollControlOutput</code>, <code>*pitchControlOutput</code>, etc... (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; //Calculates error externally controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); </pre> </code> </blockquote> ::'''Note 1:''' We calculate error externally for X and Y because certain swarm controllers need special setpoint modifiers (this way we can switch modes without effecting the default setpoint): ::'''Note 2:''' Swap out the Controller - all we need to do is create a similar function and replace ''controllerCorrectAttitudePID'' above ::'''Example:''' Follow Hand Mode Error (Crazyflie1 will have setpoint -0.5 m lower in X and +0.5 m higher in Y than your hand trackable): <blockquote> <code> <pre> ... xError1 = (xPositionHand - 0.5) - xPosition1; yError1 = (yPositionHand + 0.5) - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); ... </pre> </code> </blockquote> :4. Send Calculated Control Outputs to the Crazyflie via the Radio (code found in ''simple.cpp''): <blockquote> <code> <pre> RunCrazyflie(crRadio2, cflieCopter3, rollControlOutput3, pitchControlOutput3, yawControlOutput3, thrustControlOutput3); </pre> </code> </blockquote> ::Where the ''RunCrazyflie'' function looks like this (code in ''simple.cpp''): <blockquote> <code> <pre> int RunCrazyflie(CCrazyRadio *crRadio, CCrazyflie *cflieCopter, float rollControl, float pitchControl, float yawControl, float thrustControl) { //Timing Index Variables (**FOR TESTING ROUTINES**) int i = 0; while(cflieCopter->cycle()) { //If Crazyflie is vertical kill motors, Crash Imminent if(cflieCopter->roll() > 90){ cflieCopter->setThrust(10000); } else if(cflieCopter->roll() < -90){ cflieCopter->setThrust(10000); } else if(cflieCopter->pitch() > 90){ cflieCopter->setThrust(10000); } else if(cflieCopter->pitch() < -90){ cflieCopter->setThrust(10000); } //Otherwise Send Setpoints else if(i < 1){ //i < 200000 cflieCopter->setThrust(thrustControl); cflieCopter->setRoll(rollControl); cflieCopter->setPitch(pitchControl); cflieCopter->setYaw(-yawControl); //******SET TO NEGATIVE FOR CAMERA SYSTEM YAW BEING REVERSED!!!!**** i++; } else{ break; } } return 0; } </pre> </code> </blockquote> ::'''IMPORTANT:''' This function contains the function <code>cflieCopter->cycle()</code> which is CRITICAL to maintaining communications with the Crazyflie. The ''cycle'' function initiates communications, sends setpoints, and must be called frequently otherwise the communications will timeout and the Crazyflie will stop as a precaution. :5. Repeat steps 3 through 5 for each set of new location data...until Program END. ===Swapping Client Controller Type=== With the Swarm Platform we can plug any controller (that can be coded in C or C++) into the Client to control the Crazyflies. In steps 1, 2, and 3 of the [[#Calculating the PID's|Calculating the PID's]] section, you can see the whole process of how we calculate the control output. To replace the PID with a different controller we can follow those steps but with our new controller. So as a general idea of the process we have: ('''Note:''' This depends heavily on how your controller works, this is generalized for a single input single output controller) #Implement the New Controller Output Calculation in C as a function #Create multiple instances of this controller calculation function (for each Degree of Freedom (DOF) you need to control) and combine them into a function to calculate all controllers with 1 function call ('''Note:''' This step is for ease of code use, NOT Required) #In each Callback, call the function to Calculate the Controller output. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 7d4ecb606d5ddf4995f324e07dd6ba595fb83190 Crazyflie Swarm 0 2 126 97 2016-07-21T18:25:11Z Jnoronha 3 Added Future Project Ideas Section wikitext text/x-wiki The Crazyflie Swarm is a Networked Control platform designed for students to learn more about control and for researchers that wish to apply their research in practice. Platform development was started during the Summer of 2015 and continues to this day. Here you will find descriptions on how the platform works, how you can use it, and how you can get involved in developing the platform further! == Frequently Asked Questions == For help with common problems and troubleshooting please see the [[FAQ]]. == Background == The Crazyflie Swarm platform is based off of the ''Crazyflie'' Nano-quadcopter produced and maintained by [https://www.bitcraze.io/ Bitcraze]. The ''Crazyflie'' is completely open-source so we are able to look at and modify any part of the code and customize it to our needs. === Major Platform Components: === [[Image: High_Level_Figure_(Single_Radio_Single_Crazyflie_NO_NUMBERS_CROPPED).jpg‎|thumb|right|A high level overview of the Crazyflie Platform]] *[[PC Client Software]] *[[Firmware]] *[[USB Radio]] == Modifying the Platform == *[[Controller]] *[[Logging]] *[[Keyboard Commands]] *[[USB Radio#Changing Radio Channel|Changing Radio Channel]] *[[Flight Modes]] *[[Callbacks]] *[[Adding a Crazyflie]] *[[:Firmware]] ==Future Project Ideas== The whole concept of this Platform is to constantly expand its capabilities. If you are interested in developing this platform further [[Future Project Ideas|here are some ideas]] to get you started! *Migrating Swarm Client PID's to Firmware *Adding Parameter Support to Swarm Client *Threading Each USB Radio to speed up Computation *Crazyflie Model Development and Verification *Developing New Controllers for the Crazyflie (pending Model Development) == [https://wiki.bitcraze.io/ Bitcraze Wiki] == Bitcraze maintains their own wiki on the many Crazyflie systems. If you can't find what you are looking for here, chances are they will have something to help. 655ebf3fd5e434f919afe7e3b4316a0d2977e3f9 127 126 2016-07-21T18:25:34Z Jnoronha 3 removed a carriage return wikitext text/x-wiki The Crazyflie Swarm is a Networked Control platform designed for students to learn more about control and for researchers that wish to apply their research in practice. Platform development was started during the Summer of 2015 and continues to this day. Here you will find descriptions on how the platform works, how you can use it, and how you can get involved in developing the platform further! == Frequently Asked Questions == For help with common problems and troubleshooting please see the [[FAQ]]. == Background == The Crazyflie Swarm platform is based off of the ''Crazyflie'' Nano-quadcopter produced and maintained by [https://www.bitcraze.io/ Bitcraze]. The ''Crazyflie'' is completely open-source so we are able to look at and modify any part of the code and customize it to our needs. === Major Platform Components: === [[Image: High_Level_Figure_(Single_Radio_Single_Crazyflie_NO_NUMBERS_CROPPED).jpg‎|thumb|right|A high level overview of the Crazyflie Platform]] *[[PC Client Software]] *[[Firmware]] *[[USB Radio]] == Modifying the Platform == *[[Controller]] *[[Logging]] *[[Keyboard Commands]] *[[USB Radio#Changing Radio Channel|Changing Radio Channel]] *[[Flight Modes]] *[[Callbacks]] *[[Adding a Crazyflie]] *[[:Firmware]] ==Future Project Ideas== The whole concept of this Platform is to constantly expand its capabilities. If you are interested in developing this platform further [[Future Project Ideas|here are some ideas]] to get you started! *Migrating Swarm Client PID's to Firmware *Adding Parameter Support to Swarm Client *Threading Each USB Radio to speed up Computation *Crazyflie Model Development and Verification *Developing New Controllers for the Crazyflie (pending Model Development) == [https://wiki.bitcraze.io/ Bitcraze Wiki] == Bitcraze maintains their own wiki on the many Crazyflie systems. If you can't find what you are looking for here, chances are they will have something to help. 4b353616023e89cf446bdc9ed5bf6af0288aa2c3 128 127 2016-07-21T18:39:12Z Jnoronha 3 /* Future Project Ideas */ added link to more detailed project description wikitext text/x-wiki The Crazyflie Swarm is a Networked Control platform designed for students to learn more about control and for researchers that wish to apply their research in practice. Platform development was started during the Summer of 2015 and continues to this day. Here you will find descriptions on how the platform works, how you can use it, and how you can get involved in developing the platform further! == Frequently Asked Questions == For help with common problems and troubleshooting please see the [[FAQ]]. == Background == The Crazyflie Swarm platform is based off of the ''Crazyflie'' Nano-quadcopter produced and maintained by [https://www.bitcraze.io/ Bitcraze]. The ''Crazyflie'' is completely open-source so we are able to look at and modify any part of the code and customize it to our needs. === Major Platform Components: === [[Image: High_Level_Figure_(Single_Radio_Single_Crazyflie_NO_NUMBERS_CROPPED).jpg‎|thumb|right|A high level overview of the Crazyflie Platform]] *[[PC Client Software]] *[[Firmware]] *[[USB Radio]] == Modifying the Platform == *[[Controller]] *[[Logging]] *[[Keyboard Commands]] *[[USB Radio#Changing Radio Channel|Changing Radio Channel]] *[[Flight Modes]] *[[Callbacks]] *[[Adding a Crazyflie]] *[[:Firmware]] ==Future Project Ideas== The whole concept of this Platform is to constantly expand its capabilities. If you are interested in developing this platform further here are some ideas to get you started! Additional details on any of these ideas can be found on the [[Future Project Ideas]] page. *Migrating Swarm Client PID's to Firmware *Adding Parameter Support to Swarm Client *Threading Each USB Radio to speed up Computation *Crazyflie Model Development and Verification *Developing New Controllers for the Crazyflie (pending Model Development) == [https://wiki.bitcraze.io/ Bitcraze Wiki] == Bitcraze maintains their own wiki on the many Crazyflie systems. If you can't find what you are looking for here, chances are they will have something to help. 12d746527b02a1f37c5636773419960073727c1c 129 128 2016-07-21T18:48:45Z Jnoronha 3 /* Future Project Ideas */ added a few more ideas wikitext text/x-wiki The Crazyflie Swarm is a Networked Control platform designed for students to learn more about control and for researchers that wish to apply their research in practice. Platform development was started during the Summer of 2015 and continues to this day. Here you will find descriptions on how the platform works, how you can use it, and how you can get involved in developing the platform further! == Frequently Asked Questions == For help with common problems and troubleshooting please see the [[FAQ]]. == Background == The Crazyflie Swarm platform is based off of the ''Crazyflie'' Nano-quadcopter produced and maintained by [https://www.bitcraze.io/ Bitcraze]. The ''Crazyflie'' is completely open-source so we are able to look at and modify any part of the code and customize it to our needs. === Major Platform Components: === [[Image: High_Level_Figure_(Single_Radio_Single_Crazyflie_NO_NUMBERS_CROPPED).jpg‎|thumb|right|A high level overview of the Crazyflie Platform]] *[[PC Client Software]] *[[Firmware]] *[[USB Radio]] == Modifying the Platform == *[[Controller]] *[[Logging]] *[[Keyboard Commands]] *[[USB Radio#Changing Radio Channel|Changing Radio Channel]] *[[Flight Modes]] *[[Callbacks]] *[[Adding a Crazyflie]] *[[:Firmware]] ==Future Project Ideas== The whole concept of this Platform is to constantly expand its capabilities. If you are interested in developing this platform further here are some ideas to get you started! Additional details on any of these ideas can be found on the [[Future Project Ideas]] page. *Migrating Swarm Client PID's to Firmware *Adding Parameter Support to Swarm Client *Threading Each USB Radio to speed up Computation *Crazyflie Model Development and Verification *Developing New Controllers for the Crazyflie (pending Model Development) *Develop Communications Network Between Crazyflies *Trilateration Position Estimation using a Swarm == [https://wiki.bitcraze.io/ Bitcraze Wiki] == Bitcraze maintains their own wiki on the many Crazyflie systems. If you can't find what you are looking for here, chances are they will have something to help. f4a85985645b36236cd6da453966219729392ac6 130 129 2016-07-21T18:50:38Z Jnoronha 3 /* Future Project Ideas */ added pid tuning idea wikitext text/x-wiki The Crazyflie Swarm is a Networked Control platform designed for students to learn more about control and for researchers that wish to apply their research in practice. Platform development was started during the Summer of 2015 and continues to this day. Here you will find descriptions on how the platform works, how you can use it, and how you can get involved in developing the platform further! == Frequently Asked Questions == For help with common problems and troubleshooting please see the [[FAQ]]. == Background == The Crazyflie Swarm platform is based off of the ''Crazyflie'' Nano-quadcopter produced and maintained by [https://www.bitcraze.io/ Bitcraze]. The ''Crazyflie'' is completely open-source so we are able to look at and modify any part of the code and customize it to our needs. === Major Platform Components: === [[Image: High_Level_Figure_(Single_Radio_Single_Crazyflie_NO_NUMBERS_CROPPED).jpg‎|thumb|right|A high level overview of the Crazyflie Platform]] *[[PC Client Software]] *[[Firmware]] *[[USB Radio]] == Modifying the Platform == *[[Controller]] *[[Logging]] *[[Keyboard Commands]] *[[USB Radio#Changing Radio Channel|Changing Radio Channel]] *[[Flight Modes]] *[[Callbacks]] *[[Adding a Crazyflie]] *[[:Firmware]] ==Future Project Ideas== The whole concept of this Platform is to constantly expand its capabilities. If you are interested in developing this platform further here are some ideas to get you started! Additional details on any of these ideas can be found on the [[Future Project Ideas]] page. *Migrating Swarm Client PID's to Firmware *Tuning X, Y, and Z Location PID's for Faster Response *Adding Parameter Support to Swarm Client *Threading Each USB Radio to speed up Computation *Crazyflie Model Development and Verification *Developing New Controllers for the Crazyflie (pending Model Development) *Develop Communications Network Between Crazyflies *Trilateration Position Estimation using a Swarm == [https://wiki.bitcraze.io/ Bitcraze Wiki] == Bitcraze maintains their own wiki on the many Crazyflie systems. If you can't find what you are looking for here, chances are they will have something to help. 41267c5d3351c9d7a8a79454a4c93eb9717e929c Keyboard Commands 0 41 137 2016-07-26T16:44:47Z Jnoronha 3 completed Keyboard Input code wikitext text/x-wiki Keyboard commands give the user the ability to modify variables during a flight test. The actions each key performs is completely customizable and can trigger anything from just adjusting a PID constant, to executing complex functions. ==Reading the Keyboard Input== We use the <code>select()</code> function for a non-blocking method to read the keyboard input from the <code>STDIN</code> file descriptor in linux. The function below is what we currently use to read the keyboard. (The function was provided by Dr. Phillip Jones): :1. First we need to establish the base functions that we will use to read the key input (code found in ''vrpn.cpp''): <blockquote> <code> <pre> ////////////////////////////////////////////////// // kbhit // // Descption: used select to do a non blocking // // read of stdin. // // // ////////////////////////////////////////////////// int kbhit() { struct timeval tv; fd_set fds; tv.tv_sec = 0; tv.tv_usec = 0; FD_ZERO(&fds); FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0 select(STDIN_FILENO+1, &fds, NULL, NULL, &tv); return FD_ISSET(STDIN_FILENO, &fds); } </pre> </code> </blockquote> ::Then we can make it non-blocking code with the following: <blockquote> <code> <pre> ////////////////////////////////////////////////// // nonblock // // Descption: Turn off connoical mode so the // // user does not need to hit enter after // // pressing a key // // // ////////////////////////////////////////////////// void nonblock(int state) { struct termios ttystate; //get the terminal state tcgetattr(STDIN_FILENO, &ttystate); if (state==1) { //turn off canonical mode ttystate.c_lflag &= ~ICANON; //minimum of number input read. ttystate.c_cc[VMIN] = 1; } else if (state==0) { //turn on canonical mode ttystate.c_lflag |= ICANON; } //set the terminal attributes. tcsetattr(STDIN_FILENO, TCSANOW, &ttystate); } </pre> </code> </blockquote> :2. Reading the Keypress (code in ''vrpn.cpp''): <blockquote> <code> <pre> nonblock(1); usleep(1); i = kbhit(); //keyboard hit (state change) if (i!=0) //If state has changed, read and record key value { keystroke_now = fgetc(stdin); if (keystroke_now == 'q') i=1; else{ i=0; } } //END IF readKeyboard(); //Uses key value input to trigger actions </pre> </code> </blockquote> ::All this code is doing is checking the <code>STDIN</code> file descriptor for a state change, if it has then read that change and record the key value that was pressed. :3. Using the Key value to trigger actions (code in ''vrpn.cpp''): <blockquote> <code> <pre> void readKeyboard() { //========Reads Keystrokes from Keyboard========== nonblock(1); if (keystroke_now != keystroke_prev) { //If the keyvalue has changed (Debouncing safety) /* if (keystroke_now == 'w') { yPositionDesired1 -= 0.2; cout << "New Y Setpoint: " << yPositionDesired1 << endl; } else if (keystroke_now == 's') { yPositionDesired1 += 0.2; cout << "New Y Setpoint: " << yPositionDesired1 << endl; } else if (keystroke_now == 'a') { xPositionDesired1 -= 0.2; cout << "New X Setpoint: " << xPositionDesired1 << endl; } else if (keystroke_now == 'd') { xPositionDesired1 += 0.2; cout << "New X Setpoint: " << xPositionDesired1 << endl; } else if (keystroke_now == 'r') { zPositionDesired1 += 0.2; cout << "New Z Setpoint: " << zPositionDesired1 << endl; } else if (keystroke_now == 'f') { zPositionDesired1 -= 0.2; cout << "New Z Setpoint: " << zPositionDesired1 << endl; } */ //Commented out above inputs if (keystroke_now == '1') { yawDesired1 += 45.0; cout << "New Yaw Setpoint: " << yawDesired1 << endl; } else if (keystroke_now == '2') { yawDesired1 -= 45.0; cout << "New Yaw Setpoint: " << yawDesired1 << endl; } else if (keystroke_now == 'k') { cflieCopter1->m_enumFlightMode = GROUNDED_MODE; if(cflieCopter2){ cflieCopter2->m_enumFlightMode = GROUNDED_MODE;} if(cflieCopter3){ cflieCopter3->m_enumFlightMode = GROUNDED_MODE;} if(cflieCopter4){ cflieCopter4->m_enumFlightMode = GROUNDED_MODE;} } else if (keystroke_now == 'e') { cflieCopter1->m_enumFlightMode = LANDING_MODE; if(cflieCopter2){ cflieCopter2->m_enumFlightMode = LANDING_MODE;} if(cflieCopter3){ cflieCopter3->m_enumFlightMode = LANDING_MODE;} if(cflieCopter4){ cflieCopter4->m_enumFlightMode = LANDING_MODE;} handMode = 0; // landingMode ^= 1; // mirrorMode = 0; cout << "Landing Mode Enabled" << endl; } else if (keystroke_now == 'm') { cflieCopter1->m_enumFlightMode = MIRROR_MODE; if(cflieCopter2){ cflieCopter2->m_enumFlightMode = MIRROR_MODE;} if(cflieCopter3){ cflieCopter3->m_enumFlightMode = MIRROR_MODE;} if(cflieCopter4){ cflieCopter4->m_enumFlightMode = MIRROR_MODE;} // mirrorMode ^= 1; cout << "Mirror Mode Enabled" << endl; } else if (keystroke_now == 'h') { handMode = 1; cout << "Hand Mode Enabled" << endl; } else if (keystroke_now == 't') { cflieCopter1->m_enumFlightMode = TAKEOFF_MODE; // takeOff1 = 1; takeOffTime1 = cflieCopter1->currentTime() - initTime1; } else if (keystroke_now == 'y') { cflieCopter2->m_enumFlightMode = TAKEOFF_MODE; // takeOff2 = 1; takeOffTime2 = cflieCopter2->currentTime() - initTime2; } else if (keystroke_now == 'u') { cflieCopter3->m_enumFlightMode = TAKEOFF_MODE; // takeOff3 = 1; takeOffTime3 = cflieCopter3->currentTime() - initTime3; } else if (keystroke_now == 'i') { cflieCopter4->m_enumFlightMode = TAKEOFF_MODE; // takeOff4 = 1; takeOffTime4 = cflieCopter4->currentTime() - initTime4; } // else if (keystroke_now == '`') { // tcp_server_ON ^= 1; // } else if (keystroke_now == '1') { // tcp_client_ON ^= 1; // } // else if (keystroke_now == 'o') { // flap = 1; // } // else if (keystroke_now == 'l') { // flap = 0; // } keystroke_prev = keystroke_now; } nonblock(0); }//END readKeyboard() </pre> </code> </blockquote> ::This is just a bunch of 'if' checks that activate if a certain key has been pressed. ::*So we can see that the first 8 options just simply add or subtract a constant value to a variable in the code whenever that key is pressed. ::*The options after that are what trigger different [[:Flight States]], telling the Crazyflie to do things like ''Take-Off'', or to ''Fly in Formation'', or to ''Land''. These are more complex functions and can change the behavior of the entire swarm! See the [[:Flight States]] page for more information on this. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> d2d522e6ba1f3e4d4772b5fc48a5858a31a9675d 138 137 2016-07-26T16:47:31Z Jnoronha 3 Added keyboard input flow chart wikitext text/x-wiki Keyboard commands give the user the ability to modify variables during a flight test. The actions each key performs is completely customizable and can trigger anything from just adjusting a PID constant, to executing complex functions. To get the basic idea of how the function works, here is a flow chart of the process and an example trigger: [[Image:Keyboard_Input.png]] ==Reading the Keyboard Input== We use the <code>select()</code> function for a non-blocking method to read the keyboard input from the <code>STDIN</code> file descriptor in linux. The function below is what we currently use to read the keyboard. (The function was provided by Dr. Phillip Jones): :1. First we need to establish the base functions that we will use to read the key input (code found in ''vrpn.cpp''): <blockquote> <code> <pre> ////////////////////////////////////////////////// // kbhit // // Descption: used select to do a non blocking // // read of stdin. // // // ////////////////////////////////////////////////// int kbhit() { struct timeval tv; fd_set fds; tv.tv_sec = 0; tv.tv_usec = 0; FD_ZERO(&fds); FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0 select(STDIN_FILENO+1, &fds, NULL, NULL, &tv); return FD_ISSET(STDIN_FILENO, &fds); } </pre> </code> </blockquote> ::Then we can make it non-blocking code with the following: <blockquote> <code> <pre> ////////////////////////////////////////////////// // nonblock // // Descption: Turn off connoical mode so the // // user does not need to hit enter after // // pressing a key // // // ////////////////////////////////////////////////// void nonblock(int state) { struct termios ttystate; //get the terminal state tcgetattr(STDIN_FILENO, &ttystate); if (state==1) { //turn off canonical mode ttystate.c_lflag &= ~ICANON; //minimum of number input read. ttystate.c_cc[VMIN] = 1; } else if (state==0) { //turn on canonical mode ttystate.c_lflag |= ICANON; } //set the terminal attributes. tcsetattr(STDIN_FILENO, TCSANOW, &ttystate); } </pre> </code> </blockquote> :2. Reading the Keypress (code in ''vrpn.cpp''): <blockquote> <code> <pre> nonblock(1); usleep(1); i = kbhit(); //keyboard hit (state change) if (i!=0) //If state has changed, read and record key value { keystroke_now = fgetc(stdin); if (keystroke_now == 'q') i=1; else{ i=0; } } //END IF readKeyboard(); //Uses key value input to trigger actions </pre> </code> </blockquote> ::All this code is doing is checking the <code>STDIN</code> file descriptor for a state change, if it has then read that change and record the key value that was pressed. :3. Using the Key value to trigger actions (code in ''vrpn.cpp''): <blockquote> <code> <pre> void readKeyboard() { //========Reads Keystrokes from Keyboard========== nonblock(1); if (keystroke_now != keystroke_prev) { //If the keyvalue has changed (Debouncing safety) /* if (keystroke_now == 'w') { yPositionDesired1 -= 0.2; cout << "New Y Setpoint: " << yPositionDesired1 << endl; } else if (keystroke_now == 's') { yPositionDesired1 += 0.2; cout << "New Y Setpoint: " << yPositionDesired1 << endl; } else if (keystroke_now == 'a') { xPositionDesired1 -= 0.2; cout << "New X Setpoint: " << xPositionDesired1 << endl; } else if (keystroke_now == 'd') { xPositionDesired1 += 0.2; cout << "New X Setpoint: " << xPositionDesired1 << endl; } else if (keystroke_now == 'r') { zPositionDesired1 += 0.2; cout << "New Z Setpoint: " << zPositionDesired1 << endl; } else if (keystroke_now == 'f') { zPositionDesired1 -= 0.2; cout << "New Z Setpoint: " << zPositionDesired1 << endl; } */ //Commented out above inputs if (keystroke_now == '1') { yawDesired1 += 45.0; cout << "New Yaw Setpoint: " << yawDesired1 << endl; } else if (keystroke_now == '2') { yawDesired1 -= 45.0; cout << "New Yaw Setpoint: " << yawDesired1 << endl; } else if (keystroke_now == 'k') { cflieCopter1->m_enumFlightMode = GROUNDED_MODE; if(cflieCopter2){ cflieCopter2->m_enumFlightMode = GROUNDED_MODE;} if(cflieCopter3){ cflieCopter3->m_enumFlightMode = GROUNDED_MODE;} if(cflieCopter4){ cflieCopter4->m_enumFlightMode = GROUNDED_MODE;} } else if (keystroke_now == 'e') { cflieCopter1->m_enumFlightMode = LANDING_MODE; if(cflieCopter2){ cflieCopter2->m_enumFlightMode = LANDING_MODE;} if(cflieCopter3){ cflieCopter3->m_enumFlightMode = LANDING_MODE;} if(cflieCopter4){ cflieCopter4->m_enumFlightMode = LANDING_MODE;} handMode = 0; // landingMode ^= 1; // mirrorMode = 0; cout << "Landing Mode Enabled" << endl; } else if (keystroke_now == 'm') { cflieCopter1->m_enumFlightMode = MIRROR_MODE; if(cflieCopter2){ cflieCopter2->m_enumFlightMode = MIRROR_MODE;} if(cflieCopter3){ cflieCopter3->m_enumFlightMode = MIRROR_MODE;} if(cflieCopter4){ cflieCopter4->m_enumFlightMode = MIRROR_MODE;} // mirrorMode ^= 1; cout << "Mirror Mode Enabled" << endl; } else if (keystroke_now == 'h') { handMode = 1; cout << "Hand Mode Enabled" << endl; } else if (keystroke_now == 't') { cflieCopter1->m_enumFlightMode = TAKEOFF_MODE; // takeOff1 = 1; takeOffTime1 = cflieCopter1->currentTime() - initTime1; } else if (keystroke_now == 'y') { cflieCopter2->m_enumFlightMode = TAKEOFF_MODE; // takeOff2 = 1; takeOffTime2 = cflieCopter2->currentTime() - initTime2; } else if (keystroke_now == 'u') { cflieCopter3->m_enumFlightMode = TAKEOFF_MODE; // takeOff3 = 1; takeOffTime3 = cflieCopter3->currentTime() - initTime3; } else if (keystroke_now == 'i') { cflieCopter4->m_enumFlightMode = TAKEOFF_MODE; // takeOff4 = 1; takeOffTime4 = cflieCopter4->currentTime() - initTime4; } // else if (keystroke_now == '`') { // tcp_server_ON ^= 1; // } else if (keystroke_now == '1') { // tcp_client_ON ^= 1; // } // else if (keystroke_now == 'o') { // flap = 1; // } // else if (keystroke_now == 'l') { // flap = 0; // } keystroke_prev = keystroke_now; } nonblock(0); }//END readKeyboard() </pre> </code> </blockquote> ::This is just a bunch of 'if' checks that activate if a certain key has been pressed. ::*So we can see that the first 8 options just simply add or subtract a constant value to a variable in the code whenever that key is pressed. ::*The options after that are what trigger different [[:Flight States]], telling the Crazyflie to do things like ''Take-Off'', or to ''Fly in Formation'', or to ''Land''. These are more complex functions and can change the behavior of the entire swarm! See the [[:Flight States]] page for more information on this. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 0ddfb5960eaf8c401cd3dc64e2d3d61c9e5ea0e3 139 138 2016-07-26T16:49:23Z Jnoronha 3 Fixed flight state links to Flight Mode links wikitext text/x-wiki Keyboard commands give the user the ability to modify variables during a flight test. The actions each key performs is completely customizable and can trigger anything from just adjusting a PID constant, to executing complex functions. To get the basic idea of how the function works, here is a flow chart of the process and an example trigger: [[Image:Keyboard_Input.png]] ==Reading the Keyboard Input== We use the <code>select()</code> function for a non-blocking method to read the keyboard input from the <code>STDIN</code> file descriptor in linux. The function below is what we currently use to read the keyboard. (The function was provided by Dr. Phillip Jones): :1. First we need to establish the base functions that we will use to read the key input (code found in ''vrpn.cpp''): <blockquote> <code> <pre> ////////////////////////////////////////////////// // kbhit // // Descption: used select to do a non blocking // // read of stdin. // // // ////////////////////////////////////////////////// int kbhit() { struct timeval tv; fd_set fds; tv.tv_sec = 0; tv.tv_usec = 0; FD_ZERO(&fds); FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0 select(STDIN_FILENO+1, &fds, NULL, NULL, &tv); return FD_ISSET(STDIN_FILENO, &fds); } </pre> </code> </blockquote> ::Then we can make it non-blocking code with the following: <blockquote> <code> <pre> ////////////////////////////////////////////////// // nonblock // // Descption: Turn off connoical mode so the // // user does not need to hit enter after // // pressing a key // // // ////////////////////////////////////////////////// void nonblock(int state) { struct termios ttystate; //get the terminal state tcgetattr(STDIN_FILENO, &ttystate); if (state==1) { //turn off canonical mode ttystate.c_lflag &= ~ICANON; //minimum of number input read. ttystate.c_cc[VMIN] = 1; } else if (state==0) { //turn on canonical mode ttystate.c_lflag |= ICANON; } //set the terminal attributes. tcsetattr(STDIN_FILENO, TCSANOW, &ttystate); } </pre> </code> </blockquote> :2. Reading the Keypress (code in ''vrpn.cpp''): <blockquote> <code> <pre> nonblock(1); usleep(1); i = kbhit(); //keyboard hit (state change) if (i!=0) //If state has changed, read and record key value { keystroke_now = fgetc(stdin); if (keystroke_now == 'q') i=1; else{ i=0; } } //END IF readKeyboard(); //Uses key value input to trigger actions </pre> </code> </blockquote> ::All this code is doing is checking the <code>STDIN</code> file descriptor for a state change, if it has then read that change and record the key value that was pressed. :3. Using the Key value to trigger actions (code in ''vrpn.cpp''): <blockquote> <code> <pre> void readKeyboard() { //========Reads Keystrokes from Keyboard========== nonblock(1); if (keystroke_now != keystroke_prev) { //If the keyvalue has changed (Debouncing safety) /* if (keystroke_now == 'w') { yPositionDesired1 -= 0.2; cout << "New Y Setpoint: " << yPositionDesired1 << endl; } else if (keystroke_now == 's') { yPositionDesired1 += 0.2; cout << "New Y Setpoint: " << yPositionDesired1 << endl; } else if (keystroke_now == 'a') { xPositionDesired1 -= 0.2; cout << "New X Setpoint: " << xPositionDesired1 << endl; } else if (keystroke_now == 'd') { xPositionDesired1 += 0.2; cout << "New X Setpoint: " << xPositionDesired1 << endl; } else if (keystroke_now == 'r') { zPositionDesired1 += 0.2; cout << "New Z Setpoint: " << zPositionDesired1 << endl; } else if (keystroke_now == 'f') { zPositionDesired1 -= 0.2; cout << "New Z Setpoint: " << zPositionDesired1 << endl; } */ //Commented out above inputs if (keystroke_now == '1') { yawDesired1 += 45.0; cout << "New Yaw Setpoint: " << yawDesired1 << endl; } else if (keystroke_now == '2') { yawDesired1 -= 45.0; cout << "New Yaw Setpoint: " << yawDesired1 << endl; } else if (keystroke_now == 'k') { cflieCopter1->m_enumFlightMode = GROUNDED_MODE; if(cflieCopter2){ cflieCopter2->m_enumFlightMode = GROUNDED_MODE;} if(cflieCopter3){ cflieCopter3->m_enumFlightMode = GROUNDED_MODE;} if(cflieCopter4){ cflieCopter4->m_enumFlightMode = GROUNDED_MODE;} } else if (keystroke_now == 'e') { cflieCopter1->m_enumFlightMode = LANDING_MODE; if(cflieCopter2){ cflieCopter2->m_enumFlightMode = LANDING_MODE;} if(cflieCopter3){ cflieCopter3->m_enumFlightMode = LANDING_MODE;} if(cflieCopter4){ cflieCopter4->m_enumFlightMode = LANDING_MODE;} handMode = 0; // landingMode ^= 1; // mirrorMode = 0; cout << "Landing Mode Enabled" << endl; } else if (keystroke_now == 'm') { cflieCopter1->m_enumFlightMode = MIRROR_MODE; if(cflieCopter2){ cflieCopter2->m_enumFlightMode = MIRROR_MODE;} if(cflieCopter3){ cflieCopter3->m_enumFlightMode = MIRROR_MODE;} if(cflieCopter4){ cflieCopter4->m_enumFlightMode = MIRROR_MODE;} // mirrorMode ^= 1; cout << "Mirror Mode Enabled" << endl; } else if (keystroke_now == 'h') { handMode = 1; cout << "Hand Mode Enabled" << endl; } else if (keystroke_now == 't') { cflieCopter1->m_enumFlightMode = TAKEOFF_MODE; // takeOff1 = 1; takeOffTime1 = cflieCopter1->currentTime() - initTime1; } else if (keystroke_now == 'y') { cflieCopter2->m_enumFlightMode = TAKEOFF_MODE; // takeOff2 = 1; takeOffTime2 = cflieCopter2->currentTime() - initTime2; } else if (keystroke_now == 'u') { cflieCopter3->m_enumFlightMode = TAKEOFF_MODE; // takeOff3 = 1; takeOffTime3 = cflieCopter3->currentTime() - initTime3; } else if (keystroke_now == 'i') { cflieCopter4->m_enumFlightMode = TAKEOFF_MODE; // takeOff4 = 1; takeOffTime4 = cflieCopter4->currentTime() - initTime4; } // else if (keystroke_now == '`') { // tcp_server_ON ^= 1; // } else if (keystroke_now == '1') { // tcp_client_ON ^= 1; // } // else if (keystroke_now == 'o') { // flap = 1; // } // else if (keystroke_now == 'l') { // flap = 0; // } keystroke_prev = keystroke_now; } nonblock(0); }//END readKeyboard() </pre> </code> </blockquote> ::This is just a bunch of 'if' checks that activate if a certain key has been pressed. ::*So we can see that the first 8 options just simply add or subtract a constant value to a variable in the code whenever that key is pressed. ::*The options after that are what trigger different [[:Flight Modes]], telling the Crazyflie to do things like ''Take-Off'', or to ''Fly in Formation'', or to ''Land''. These are more complex functions and can change the behavior of the entire swarm! See the [[:Flight Modes]] page for more information on this. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 94c96f056cf0d8431bf3d087e23faf9b10202091 140 139 2016-07-26T17:20:13Z Jnoronha 3 added list of current keyboard commands wikitext text/x-wiki Keyboard commands give the user the ability to modify variables during a flight test. The actions each key performs is completely customizable and can trigger anything from just adjusting a PID constant, to executing complex functions. To get the basic idea of how the function works, here is a flow chart of the process and an example trigger: [[Image:Keyboard_Input.png]] ==List of Current Keyboard Commands== ===Movement Commands=== ::*'w' - Moves Crazyflie1 Forward by 0.2 meters (- y setpoint) '''(COMMENTED OUT)''' ::*'s' - Moves Crazyflie1 Backward by 0.2 meters (+ y setpoint) '''(COMMENTED OUT)''' ::*'a' - Moves Crazyflie1 Left by 0.2 meters (- x setpoint) '''(COMMENTED OUT)''' ::*'d' - Moves Crazyflie1 Right by 0.2 meters (+ x setpoint) '''(COMMENTED OUT)''' ::*'r' - Moves Crazyflie1 UP by 0.2 meters (+ z setpoint) '''(COMMENTED OUT)''' ::*'f' - Moves Crazyflie1 Down by 0.2 meters (- z setpoint) '''(COMMENTED OUT)''' ::*'1' - Rotates Yaw of Crazyflie1 +45 degrees ::*'2' - Rotates Yaw of Crazyflie1 -45 degrees ===Flight Mode Commands=== ::*'k' - EMERGENCY STOP kill ALL Crazyflie engines '''(set all thrust to 0)''' ::*'h' - Hand Mode '''(for ALL Crazyflies)''' ::*'e' - Landing Mode '''(for ALL Crazyflies)''' ::*'t' - Crazyflie1 Take-Off ::*'y' - Crazyflie2 Take-Off ::*'u' - Crazyflie3 Take-Off ::*'i' - Crazyflie4 Take-Off ::*'h' - Hand Gesture Mode '''(for ALL Crazyflies)''' ::*'m' - Mirror Mode '''(for ALL Crazyflies)''' ===Utility Commands=== ::*ctrl+c - Quits Program, performs all cleanup. ===Obsolete Key Commands=== ::*'q' - Ends Main Loop '''(OBSOLETE - Replaced with ctrl + c)''' ::*'`' - Enables TCP Server on the Swarm Client (for '''sending''' information to Swarm Clients on different computers) ::*'l' - Enables TCP Client on the Swarm Client (for '''receiving''' information from Swarm Clients on different computers) ::*'o' - Enable Flap Mode (used for testing Crazyflie Powered Flapping Wing Project) ::*'1' - Disable Flap Mode ==Reading the Keyboard Input== We use the <code>select()</code> function for a non-blocking method to read the keyboard input from the <code>STDIN</code> file descriptor in linux. The function below is what we currently use to read the keyboard. (The function was provided by Dr. Phillip Jones): :1. First we need to establish the base functions that we will use to read the key input (code found in ''vrpn.cpp''): <blockquote> <code> <pre> ////////////////////////////////////////////////// // kbhit // // Descption: used select to do a non blocking // // read of stdin. // // // ////////////////////////////////////////////////// int kbhit() { struct timeval tv; fd_set fds; tv.tv_sec = 0; tv.tv_usec = 0; FD_ZERO(&fds); FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0 select(STDIN_FILENO+1, &fds, NULL, NULL, &tv); return FD_ISSET(STDIN_FILENO, &fds); } </pre> </code> </blockquote> ::Then we can make it non-blocking code with the following: <blockquote> <code> <pre> ////////////////////////////////////////////////// // nonblock // // Descption: Turn off connoical mode so the // // user does not need to hit enter after // // pressing a key // // // ////////////////////////////////////////////////// void nonblock(int state) { struct termios ttystate; //get the terminal state tcgetattr(STDIN_FILENO, &ttystate); if (state==1) { //turn off canonical mode ttystate.c_lflag &= ~ICANON; //minimum of number input read. ttystate.c_cc[VMIN] = 1; } else if (state==0) { //turn on canonical mode ttystate.c_lflag |= ICANON; } //set the terminal attributes. tcsetattr(STDIN_FILENO, TCSANOW, &ttystate); } </pre> </code> </blockquote> :2. Reading the Keypress (code in ''vrpn.cpp''): <blockquote> <code> <pre> nonblock(1); usleep(1); i = kbhit(); //keyboard hit (state change) if (i!=0) //If state has changed, read and record key value { keystroke_now = fgetc(stdin); if (keystroke_now == 'q') i=1; else{ i=0; } } //END IF readKeyboard(); //Uses key value input to trigger actions </pre> </code> </blockquote> ::All this code is doing is checking the <code>STDIN</code> file descriptor for a state change, if it has then read that change and record the key value that was pressed. :3. Using the Key value to trigger actions (code in ''vrpn.cpp''): <blockquote> <code> <pre> void readKeyboard() { //========Reads Keystrokes from Keyboard========== nonblock(1); if (keystroke_now != keystroke_prev) { //If the keyvalue has changed (Debouncing safety) /* if (keystroke_now == 'w') { yPositionDesired1 -= 0.2; cout << "New Y Setpoint: " << yPositionDesired1 << endl; } else if (keystroke_now == 's') { yPositionDesired1 += 0.2; cout << "New Y Setpoint: " << yPositionDesired1 << endl; } else if (keystroke_now == 'a') { xPositionDesired1 -= 0.2; cout << "New X Setpoint: " << xPositionDesired1 << endl; } else if (keystroke_now == 'd') { xPositionDesired1 += 0.2; cout << "New X Setpoint: " << xPositionDesired1 << endl; } else if (keystroke_now == 'r') { zPositionDesired1 += 0.2; cout << "New Z Setpoint: " << zPositionDesired1 << endl; } else if (keystroke_now == 'f') { zPositionDesired1 -= 0.2; cout << "New Z Setpoint: " << zPositionDesired1 << endl; } */ //Commented out above inputs if (keystroke_now == '1') { yawDesired1 += 45.0; cout << "New Yaw Setpoint: " << yawDesired1 << endl; } else if (keystroke_now == '2') { yawDesired1 -= 45.0; cout << "New Yaw Setpoint: " << yawDesired1 << endl; } else if (keystroke_now == 'k') { cflieCopter1->m_enumFlightMode = GROUNDED_MODE; if(cflieCopter2){ cflieCopter2->m_enumFlightMode = GROUNDED_MODE;} if(cflieCopter3){ cflieCopter3->m_enumFlightMode = GROUNDED_MODE;} if(cflieCopter4){ cflieCopter4->m_enumFlightMode = GROUNDED_MODE;} } else if (keystroke_now == 'e') { cflieCopter1->m_enumFlightMode = LANDING_MODE; if(cflieCopter2){ cflieCopter2->m_enumFlightMode = LANDING_MODE;} if(cflieCopter3){ cflieCopter3->m_enumFlightMode = LANDING_MODE;} if(cflieCopter4){ cflieCopter4->m_enumFlightMode = LANDING_MODE;} handMode = 0; // landingMode ^= 1; // mirrorMode = 0; cout << "Landing Mode Enabled" << endl; } else if (keystroke_now == 'm') { cflieCopter1->m_enumFlightMode = MIRROR_MODE; if(cflieCopter2){ cflieCopter2->m_enumFlightMode = MIRROR_MODE;} if(cflieCopter3){ cflieCopter3->m_enumFlightMode = MIRROR_MODE;} if(cflieCopter4){ cflieCopter4->m_enumFlightMode = MIRROR_MODE;} // mirrorMode ^= 1; cout << "Mirror Mode Enabled" << endl; } else if (keystroke_now == 'h') { handMode = 1; cout << "Hand Mode Enabled" << endl; } else if (keystroke_now == 't') { cflieCopter1->m_enumFlightMode = TAKEOFF_MODE; // takeOff1 = 1; takeOffTime1 = cflieCopter1->currentTime() - initTime1; } else if (keystroke_now == 'y') { cflieCopter2->m_enumFlightMode = TAKEOFF_MODE; // takeOff2 = 1; takeOffTime2 = cflieCopter2->currentTime() - initTime2; } else if (keystroke_now == 'u') { cflieCopter3->m_enumFlightMode = TAKEOFF_MODE; // takeOff3 = 1; takeOffTime3 = cflieCopter3->currentTime() - initTime3; } else if (keystroke_now == 'i') { cflieCopter4->m_enumFlightMode = TAKEOFF_MODE; // takeOff4 = 1; takeOffTime4 = cflieCopter4->currentTime() - initTime4; } // else if (keystroke_now == '`') { // tcp_server_ON ^= 1; // } else if (keystroke_now == '1') { // tcp_client_ON ^= 1; // } // else if (keystroke_now == 'o') { // flap = 1; // } // else if (keystroke_now == 'l') { // flap = 0; // } keystroke_prev = keystroke_now; } nonblock(0); }//END readKeyboard() </pre> </code> </blockquote> ::This is just a bunch of 'if' checks that activate if a certain key has been pressed. ::*So we can see that the first 8 options just simply add or subtract a constant value to a variable in the code whenever that key is pressed. ::*The options after that are what trigger different [[:Flight Modes]], telling the Crazyflie to do things like ''Take-Off'', or to ''Fly in Formation'', or to ''Land''. These are more complex functions and can change the behavior of the entire swarm! See the [[:Flight Modes]] page for more information on this. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> eaa81d95ade4003bd6b25c6a0a2e902bbaa474f7 141 140 2016-07-26T17:21:20Z Jnoronha 3 Added command list timestamp wikitext text/x-wiki Keyboard commands give the user the ability to modify variables during a flight test. The actions each key performs is completely customizable and can trigger anything from just adjusting a PID constant, to executing complex functions. To get the basic idea of how the function works, here is a flow chart of the process and an example trigger: [[Image:Keyboard_Input.png]] ==List of Current Keyboard Commands== (Command List as of 7/26/16) ===Movement Commands=== ::*'w' - Moves Crazyflie1 Forward by 0.2 meters (- y setpoint) '''(COMMENTED OUT)''' ::*'s' - Moves Crazyflie1 Backward by 0.2 meters (+ y setpoint) '''(COMMENTED OUT)''' ::*'a' - Moves Crazyflie1 Left by 0.2 meters (- x setpoint) '''(COMMENTED OUT)''' ::*'d' - Moves Crazyflie1 Right by 0.2 meters (+ x setpoint) '''(COMMENTED OUT)''' ::*'r' - Moves Crazyflie1 UP by 0.2 meters (+ z setpoint) '''(COMMENTED OUT)''' ::*'f' - Moves Crazyflie1 Down by 0.2 meters (- z setpoint) '''(COMMENTED OUT)''' ::*'1' - Rotates Yaw of Crazyflie1 +45 degrees ::*'2' - Rotates Yaw of Crazyflie1 -45 degrees ===Flight Mode Commands=== ::*'k' - EMERGENCY STOP kill ALL Crazyflie engines '''(set all thrust to 0)''' ::*'h' - Hand Mode '''(for ALL Crazyflies)''' ::*'e' - Landing Mode '''(for ALL Crazyflies)''' ::*'t' - Crazyflie1 Take-Off ::*'y' - Crazyflie2 Take-Off ::*'u' - Crazyflie3 Take-Off ::*'i' - Crazyflie4 Take-Off ::*'h' - Hand Gesture Mode '''(for ALL Crazyflies)''' ::*'m' - Mirror Mode '''(for ALL Crazyflies)''' ===Utility Commands=== ::*ctrl+c - Quits Program, performs all cleanup. ===Obsolete Key Commands=== ::*'q' - Ends Main Loop '''(OBSOLETE - Replaced with ctrl + c)''' ::*'`' - Enables TCP Server on the Swarm Client (for '''sending''' information to Swarm Clients on different computers) ::*'l' - Enables TCP Client on the Swarm Client (for '''receiving''' information from Swarm Clients on different computers) ::*'o' - Enable Flap Mode (used for testing Crazyflie Powered Flapping Wing Project) ::*'1' - Disable Flap Mode ==Reading the Keyboard Input== We use the <code>select()</code> function for a non-blocking method to read the keyboard input from the <code>STDIN</code> file descriptor in linux. The function below is what we currently use to read the keyboard. (The function was provided by Dr. Phillip Jones): :1. First we need to establish the base functions that we will use to read the key input (code found in ''vrpn.cpp''): <blockquote> <code> <pre> ////////////////////////////////////////////////// // kbhit // // Descption: used select to do a non blocking // // read of stdin. // // // ////////////////////////////////////////////////// int kbhit() { struct timeval tv; fd_set fds; tv.tv_sec = 0; tv.tv_usec = 0; FD_ZERO(&fds); FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0 select(STDIN_FILENO+1, &fds, NULL, NULL, &tv); return FD_ISSET(STDIN_FILENO, &fds); } </pre> </code> </blockquote> ::Then we can make it non-blocking code with the following: <blockquote> <code> <pre> ////////////////////////////////////////////////// // nonblock // // Descption: Turn off connoical mode so the // // user does not need to hit enter after // // pressing a key // // // ////////////////////////////////////////////////// void nonblock(int state) { struct termios ttystate; //get the terminal state tcgetattr(STDIN_FILENO, &ttystate); if (state==1) { //turn off canonical mode ttystate.c_lflag &= ~ICANON; //minimum of number input read. ttystate.c_cc[VMIN] = 1; } else if (state==0) { //turn on canonical mode ttystate.c_lflag |= ICANON; } //set the terminal attributes. tcsetattr(STDIN_FILENO, TCSANOW, &ttystate); } </pre> </code> </blockquote> :2. Reading the Keypress (code in ''vrpn.cpp''): <blockquote> <code> <pre> nonblock(1); usleep(1); i = kbhit(); //keyboard hit (state change) if (i!=0) //If state has changed, read and record key value { keystroke_now = fgetc(stdin); if (keystroke_now == 'q') i=1; else{ i=0; } } //END IF readKeyboard(); //Uses key value input to trigger actions </pre> </code> </blockquote> ::All this code is doing is checking the <code>STDIN</code> file descriptor for a state change, if it has then read that change and record the key value that was pressed. :3. Using the Key value to trigger actions (code in ''vrpn.cpp''): <blockquote> <code> <pre> void readKeyboard() { //========Reads Keystrokes from Keyboard========== nonblock(1); if (keystroke_now != keystroke_prev) { //If the keyvalue has changed (Debouncing safety) /* if (keystroke_now == 'w') { yPositionDesired1 -= 0.2; cout << "New Y Setpoint: " << yPositionDesired1 << endl; } else if (keystroke_now == 's') { yPositionDesired1 += 0.2; cout << "New Y Setpoint: " << yPositionDesired1 << endl; } else if (keystroke_now == 'a') { xPositionDesired1 -= 0.2; cout << "New X Setpoint: " << xPositionDesired1 << endl; } else if (keystroke_now == 'd') { xPositionDesired1 += 0.2; cout << "New X Setpoint: " << xPositionDesired1 << endl; } else if (keystroke_now == 'r') { zPositionDesired1 += 0.2; cout << "New Z Setpoint: " << zPositionDesired1 << endl; } else if (keystroke_now == 'f') { zPositionDesired1 -= 0.2; cout << "New Z Setpoint: " << zPositionDesired1 << endl; } */ //Commented out above inputs if (keystroke_now == '1') { yawDesired1 += 45.0; cout << "New Yaw Setpoint: " << yawDesired1 << endl; } else if (keystroke_now == '2') { yawDesired1 -= 45.0; cout << "New Yaw Setpoint: " << yawDesired1 << endl; } else if (keystroke_now == 'k') { cflieCopter1->m_enumFlightMode = GROUNDED_MODE; if(cflieCopter2){ cflieCopter2->m_enumFlightMode = GROUNDED_MODE;} if(cflieCopter3){ cflieCopter3->m_enumFlightMode = GROUNDED_MODE;} if(cflieCopter4){ cflieCopter4->m_enumFlightMode = GROUNDED_MODE;} } else if (keystroke_now == 'e') { cflieCopter1->m_enumFlightMode = LANDING_MODE; if(cflieCopter2){ cflieCopter2->m_enumFlightMode = LANDING_MODE;} if(cflieCopter3){ cflieCopter3->m_enumFlightMode = LANDING_MODE;} if(cflieCopter4){ cflieCopter4->m_enumFlightMode = LANDING_MODE;} handMode = 0; // landingMode ^= 1; // mirrorMode = 0; cout << "Landing Mode Enabled" << endl; } else if (keystroke_now == 'm') { cflieCopter1->m_enumFlightMode = MIRROR_MODE; if(cflieCopter2){ cflieCopter2->m_enumFlightMode = MIRROR_MODE;} if(cflieCopter3){ cflieCopter3->m_enumFlightMode = MIRROR_MODE;} if(cflieCopter4){ cflieCopter4->m_enumFlightMode = MIRROR_MODE;} // mirrorMode ^= 1; cout << "Mirror Mode Enabled" << endl; } else if (keystroke_now == 'h') { handMode = 1; cout << "Hand Mode Enabled" << endl; } else if (keystroke_now == 't') { cflieCopter1->m_enumFlightMode = TAKEOFF_MODE; // takeOff1 = 1; takeOffTime1 = cflieCopter1->currentTime() - initTime1; } else if (keystroke_now == 'y') { cflieCopter2->m_enumFlightMode = TAKEOFF_MODE; // takeOff2 = 1; takeOffTime2 = cflieCopter2->currentTime() - initTime2; } else if (keystroke_now == 'u') { cflieCopter3->m_enumFlightMode = TAKEOFF_MODE; // takeOff3 = 1; takeOffTime3 = cflieCopter3->currentTime() - initTime3; } else if (keystroke_now == 'i') { cflieCopter4->m_enumFlightMode = TAKEOFF_MODE; // takeOff4 = 1; takeOffTime4 = cflieCopter4->currentTime() - initTime4; } // else if (keystroke_now == '`') { // tcp_server_ON ^= 1; // } else if (keystroke_now == '1') { // tcp_client_ON ^= 1; // } // else if (keystroke_now == 'o') { // flap = 1; // } // else if (keystroke_now == 'l') { // flap = 0; // } keystroke_prev = keystroke_now; } nonblock(0); }//END readKeyboard() </pre> </code> </blockquote> ::This is just a bunch of 'if' checks that activate if a certain key has been pressed. ::*So we can see that the first 8 options just simply add or subtract a constant value to a variable in the code whenever that key is pressed. ::*The options after that are what trigger different [[:Flight Modes]], telling the Crazyflie to do things like ''Take-Off'', or to ''Fly in Formation'', or to ''Land''. These are more complex functions and can change the behavior of the entire swarm! See the [[:Flight Modes]] page for more information on this. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> a1db84aa1d4464fc91461da06e5f633d451fdfc8 142 141 2016-07-26T17:23:24Z Jnoronha 3 spaced the directory footer better wikitext text/x-wiki Keyboard commands give the user the ability to modify variables during a flight test. The actions each key performs is completely customizable and can trigger anything from just adjusting a PID constant, to executing complex functions. To get the basic idea of how the function works, here is a flow chart of the process and an example trigger: [[Image:Keyboard_Input.png]] ==List of Current Keyboard Commands== (Command List as of 7/26/16) ===Movement Commands=== ::*'w' - Moves Crazyflie1 Forward by 0.2 meters (- y setpoint) '''(COMMENTED OUT)''' ::*'s' - Moves Crazyflie1 Backward by 0.2 meters (+ y setpoint) '''(COMMENTED OUT)''' ::*'a' - Moves Crazyflie1 Left by 0.2 meters (- x setpoint) '''(COMMENTED OUT)''' ::*'d' - Moves Crazyflie1 Right by 0.2 meters (+ x setpoint) '''(COMMENTED OUT)''' ::*'r' - Moves Crazyflie1 UP by 0.2 meters (+ z setpoint) '''(COMMENTED OUT)''' ::*'f' - Moves Crazyflie1 Down by 0.2 meters (- z setpoint) '''(COMMENTED OUT)''' ::*'1' - Rotates Yaw of Crazyflie1 +45 degrees ::*'2' - Rotates Yaw of Crazyflie1 -45 degrees ===Flight Mode Commands=== ::*'k' - EMERGENCY STOP kill ALL Crazyflie engines '''(set all thrust to 0)''' ::*'h' - Hand Mode '''(for ALL Crazyflies)''' ::*'e' - Landing Mode '''(for ALL Crazyflies)''' ::*'t' - Crazyflie1 Take-Off ::*'y' - Crazyflie2 Take-Off ::*'u' - Crazyflie3 Take-Off ::*'i' - Crazyflie4 Take-Off ::*'h' - Hand Gesture Mode '''(for ALL Crazyflies)''' ::*'m' - Mirror Mode '''(for ALL Crazyflies)''' ===Utility Commands=== ::*ctrl+c - Quits Program, performs all cleanup. ===Obsolete Key Commands=== ::*'q' - Ends Main Loop '''(OBSOLETE - Replaced with ctrl + c)''' ::*'`' - Enables TCP Server on the Swarm Client (for '''sending''' information to Swarm Clients on different computers) ::*'l' - Enables TCP Client on the Swarm Client (for '''receiving''' information from Swarm Clients on different computers) ::*'o' - Enable Flap Mode (used for testing Crazyflie Powered Flapping Wing Project) ::*'1' - Disable Flap Mode ==Reading the Keyboard Input== We use the <code>select()</code> function for a non-blocking method to read the keyboard input from the <code>STDIN</code> file descriptor in linux. The function below is what we currently use to read the keyboard. (The function was provided by Dr. Phillip Jones): :1. First we need to establish the base functions that we will use to read the key input (code found in ''vrpn.cpp''): <blockquote> <code> <pre> ////////////////////////////////////////////////// // kbhit // // Descption: used select to do a non blocking // // read of stdin. // // // ////////////////////////////////////////////////// int kbhit() { struct timeval tv; fd_set fds; tv.tv_sec = 0; tv.tv_usec = 0; FD_ZERO(&fds); FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0 select(STDIN_FILENO+1, &fds, NULL, NULL, &tv); return FD_ISSET(STDIN_FILENO, &fds); } </pre> </code> </blockquote> ::Then we can make it non-blocking code with the following: <blockquote> <code> <pre> ////////////////////////////////////////////////// // nonblock // // Descption: Turn off connoical mode so the // // user does not need to hit enter after // // pressing a key // // // ////////////////////////////////////////////////// void nonblock(int state) { struct termios ttystate; //get the terminal state tcgetattr(STDIN_FILENO, &ttystate); if (state==1) { //turn off canonical mode ttystate.c_lflag &= ~ICANON; //minimum of number input read. ttystate.c_cc[VMIN] = 1; } else if (state==0) { //turn on canonical mode ttystate.c_lflag |= ICANON; } //set the terminal attributes. tcsetattr(STDIN_FILENO, TCSANOW, &ttystate); } </pre> </code> </blockquote> :2. Reading the Keypress (code in ''vrpn.cpp''): <blockquote> <code> <pre> nonblock(1); usleep(1); i = kbhit(); //keyboard hit (state change) if (i!=0) //If state has changed, read and record key value { keystroke_now = fgetc(stdin); if (keystroke_now == 'q') i=1; else{ i=0; } } //END IF readKeyboard(); //Uses key value input to trigger actions </pre> </code> </blockquote> ::All this code is doing is checking the <code>STDIN</code> file descriptor for a state change, if it has then read that change and record the key value that was pressed. :3. Using the Key value to trigger actions (code in ''vrpn.cpp''): <blockquote> <code> <pre> void readKeyboard() { //========Reads Keystrokes from Keyboard========== nonblock(1); if (keystroke_now != keystroke_prev) { //If the keyvalue has changed (Debouncing safety) /* if (keystroke_now == 'w') { yPositionDesired1 -= 0.2; cout << "New Y Setpoint: " << yPositionDesired1 << endl; } else if (keystroke_now == 's') { yPositionDesired1 += 0.2; cout << "New Y Setpoint: " << yPositionDesired1 << endl; } else if (keystroke_now == 'a') { xPositionDesired1 -= 0.2; cout << "New X Setpoint: " << xPositionDesired1 << endl; } else if (keystroke_now == 'd') { xPositionDesired1 += 0.2; cout << "New X Setpoint: " << xPositionDesired1 << endl; } else if (keystroke_now == 'r') { zPositionDesired1 += 0.2; cout << "New Z Setpoint: " << zPositionDesired1 << endl; } else if (keystroke_now == 'f') { zPositionDesired1 -= 0.2; cout << "New Z Setpoint: " << zPositionDesired1 << endl; } */ //Commented out above inputs if (keystroke_now == '1') { yawDesired1 += 45.0; cout << "New Yaw Setpoint: " << yawDesired1 << endl; } else if (keystroke_now == '2') { yawDesired1 -= 45.0; cout << "New Yaw Setpoint: " << yawDesired1 << endl; } else if (keystroke_now == 'k') { cflieCopter1->m_enumFlightMode = GROUNDED_MODE; if(cflieCopter2){ cflieCopter2->m_enumFlightMode = GROUNDED_MODE;} if(cflieCopter3){ cflieCopter3->m_enumFlightMode = GROUNDED_MODE;} if(cflieCopter4){ cflieCopter4->m_enumFlightMode = GROUNDED_MODE;} } else if (keystroke_now == 'e') { cflieCopter1->m_enumFlightMode = LANDING_MODE; if(cflieCopter2){ cflieCopter2->m_enumFlightMode = LANDING_MODE;} if(cflieCopter3){ cflieCopter3->m_enumFlightMode = LANDING_MODE;} if(cflieCopter4){ cflieCopter4->m_enumFlightMode = LANDING_MODE;} handMode = 0; // landingMode ^= 1; // mirrorMode = 0; cout << "Landing Mode Enabled" << endl; } else if (keystroke_now == 'm') { cflieCopter1->m_enumFlightMode = MIRROR_MODE; if(cflieCopter2){ cflieCopter2->m_enumFlightMode = MIRROR_MODE;} if(cflieCopter3){ cflieCopter3->m_enumFlightMode = MIRROR_MODE;} if(cflieCopter4){ cflieCopter4->m_enumFlightMode = MIRROR_MODE;} // mirrorMode ^= 1; cout << "Mirror Mode Enabled" << endl; } else if (keystroke_now == 'h') { handMode = 1; cout << "Hand Mode Enabled" << endl; } else if (keystroke_now == 't') { cflieCopter1->m_enumFlightMode = TAKEOFF_MODE; // takeOff1 = 1; takeOffTime1 = cflieCopter1->currentTime() - initTime1; } else if (keystroke_now == 'y') { cflieCopter2->m_enumFlightMode = TAKEOFF_MODE; // takeOff2 = 1; takeOffTime2 = cflieCopter2->currentTime() - initTime2; } else if (keystroke_now == 'u') { cflieCopter3->m_enumFlightMode = TAKEOFF_MODE; // takeOff3 = 1; takeOffTime3 = cflieCopter3->currentTime() - initTime3; } else if (keystroke_now == 'i') { cflieCopter4->m_enumFlightMode = TAKEOFF_MODE; // takeOff4 = 1; takeOffTime4 = cflieCopter4->currentTime() - initTime4; } // else if (keystroke_now == '`') { // tcp_server_ON ^= 1; // } else if (keystroke_now == '1') { // tcp_client_ON ^= 1; // } // else if (keystroke_now == 'o') { // flap = 1; // } // else if (keystroke_now == 'l') { // flap = 0; // } keystroke_prev = keystroke_now; } nonblock(0); }//END readKeyboard() </pre> </code> </blockquote> ::This is just a bunch of 'if' checks that activate if a certain key has been pressed. ::*So we can see that the first 8 options just simply add or subtract a constant value to a variable in the code whenever that key is pressed. ::*The options after that are what trigger different [[:Flight Modes]], telling the Crazyflie to do things like ''Take-Off'', or to ''Fly in Formation'', or to ''Land''. These are more complex functions and can change the behavior of the entire swarm! See the [[:Flight Modes]] page for more information on this. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 457c7874d7c4bf2e27585caaf674df862324c21a Flight Modes 0 42 143 2016-07-26T17:55:07Z Jnoronha 3 Created list of flight modes wikitext text/x-wiki Flight modes are a framework we created to allow changes to be made to the Flight behavior of the Crazyflies during a test. They have been implemented as an enum structure so that only one flight mode can be active at a time. Each Crazyflie has its own independent flight modes, so we can customize the flight patterns of each Crazyflie in the swarm separately, or as a group. The enum is shown below (code in ''CCrazyflie.h''): <blockquote> <code> <pre> enum FlightMode{ LANDING_MODE = 0, TAKEOFF_MODE = 1, HOVER_MODE = 2, MIRROR_MODE = 3, HAND_MODE = 4, GROUNDED_MODE = 5, STEP_MODE = 6, KILL_MODE = 7 }; </pre> </code> </blockquote> ==Current Flight Modes== (List as of 7/26/16) ===Simple Flight Modes=== :*Landing Mode (0): :**Changes z-setpoint to 0 and when Crazyflie is close enough to the ground automatically switch to ''Grounded Mode'' :*TakeOff Mode (1): :**Enable PID controller for autonomous flight, hold position at default coordinates :*Grounded Mode (5): :**Crazyflies Setpoints Forced to 0, NO CONTROLLER CALCULATION DONE (used for sitting on the ground waiting for command) :**'''Note:''' Also resets Controller Error to prevent integrator wind-up ===Formation Flight Modes=== :*Mirror Mode (3): :**Swarm Forms a Triangle around Crazyflie 1 :**Crazyflie 1 Moves in a Step Pattern (diagonally back and forth) :**Crazyflies 2, 3, and 4 follow Crazyflie 1 while maintaining the Triangle Formation :*Hand Mode (4): :**Crazyflies wait for Hand Gesture Commands ===Unused Flight Modes=== :*Hover Mode (2): :**'''Not used yet''' (Could be used to reset the Crazyflie setpoints back to default) :*Step Mode (6): :**Similar to Crazyflie1's behavior when in Mirror Mode, but for all Crazyflies (used to verify Model Parameters). :*Kill Mode (7): :**Discontinued version of Grounded Mode (forces all setpoints to 0 but would continue calculating Controller) ==Landing Mode== Landing Mode is more complex than some of the other modes in that when a certain condition is reached, it will automatically switch to a different Flight Mode. [[Image:Landing_Mode.png]] ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> f8887e808f5f60e9846f90c339ee5d30615cbbfb 144 143 2016-07-26T18:04:49Z Jnoronha 3 Added detailed landing mode wikitext text/x-wiki Flight modes are a framework we created to allow changes to be made to the Flight behavior of the Crazyflies during a test. They have been implemented as an enum structure so that only one flight mode can be active at a time. Each Crazyflie has its own independent flight modes, so we can customize the flight patterns of each Crazyflie in the swarm separately, or as a group. The enum is shown below (code in ''CCrazyflie.h''): <blockquote> <code> <pre> enum FlightMode{ LANDING_MODE = 0, TAKEOFF_MODE = 1, HOVER_MODE = 2, MIRROR_MODE = 3, HAND_MODE = 4, GROUNDED_MODE = 5, STEP_MODE = 6, KILL_MODE = 7 }; </pre> </code> </blockquote> ==Current Flight Modes== (List as of 7/26/16) ===Simple Flight Modes=== :*'''Landing Mode (0):''' :**Changes z-setpoint to 0 and when Crazyflie is close enough to the ground automatically switch to ''Grounded Mode'' :*'''TakeOff Mode (1):''' :**Enable PID controller for autonomous flight, hold position at default coordinates :*'''Grounded Mode (5):''' :**Crazyflies Setpoints Forced to 0, NO CONTROLLER CALCULATION DONE (used for sitting on the ground waiting for command) :**'''Note:''' Also resets Controller Error to prevent integrator wind-up ===Formation Flight Modes=== :*'''Mirror Mode (3):''' :**Swarm Forms a Triangle around Crazyflie 1 :**Crazyflie 1 Moves in a Step Pattern (diagonally back and forth) :**Crazyflies 2, 3, and 4 follow Crazyflie 1 while maintaining the Triangle Formation :*'''Hand Mode (4):''' :**Crazyflies wait for Hand Gesture Commands ===Unused Flight Modes=== :*'''Hover Mode (2):''' :**'''Not used yet''' (Could be used to reset the Crazyflie setpoints back to default) :*'''Step Mode (6):''' :**Similar to Crazyflie1's behavior when in Mirror Mode, but for all Crazyflies (used to verify Model Parameters). :*'''Kill Mode (7):''' :**Discontinued version of Grounded Mode (forces all setpoints to 0 but would continue calculating Controller) ==Landing Mode== Landing Mode is more complex than some of the other modes in that when a certain condition is reached, it will automatically switch to a different Flight Mode. A flow chart of the process is shown here: [[Image:LandingMode.png|300px]] And the code used to implement this is shown below (code in ''vrpn.cpp''): <blockquote> <code> <pre> void nearGround() //During Landing Mode checks how close to ground quad is for shutdown { if((cflieCopter1->m_enumFlightMode == LANDING_MODE) && (zPosition1 < 0.05)) { cflieCopter1->m_enumFlightMode = GROUNDED_MODE; } if(cflieCopter2){ //Only sends command if Crazyflie 2 exists for this test (CLIENT WILL CRASH IF COMMANDING NON-EXISTENT CRAZYFLIE) if((cflieCopter2->m_enumFlightMode == LANDING_MODE) && (zPosition2 < 0.05)) { cflieCopter2->m_enumFlightMode = GROUNDED_MODE; } } if(cflieCopter3){ //Only sends command if Crazyflie 3 exists for this test if((cflieCopter3->m_enumFlightMode == LANDING_MODE) && (zPosition3 < 0.05)) { cflieCopter3->m_enumFlightMode = GROUNDED_MODE; } } if(cflieCopter4){ //Only sends command if Crazyflie 4 exists for this test if((cflieCopter4->m_enumFlightMode == LANDING_MODE) && (zPosition4 < 0.05)) { cflieCopter4->m_enumFlightMode = GROUNDED_MODE; } } } </pre> </code> </blockquote> ::This function is scanned at each iteration of the mainloop. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> b15b1bc8c2dfa5e02d9310f600f9bf894ee8cc50 File:TrackingToolsCrazyflieConstellationZeroing.png 6 43 145 2016-07-27T17:46:40Z Jnoronha 3 Camera System Software with Crazyflie and Hand Constellations loaded wikitext text/x-wiki Camera System Software with Crazyflie and Hand Constellations loaded b20b4b16a3427dc104687a0ec094c2df21a8b1d5 Callbacks 0 44 146 2016-07-27T18:00:09Z Jnoronha 3 added registering the Callbacks wikitext text/x-wiki A callback is a segment of code that will run only when a certain condition is satisfied. For the Swarm Platform, the callbacks we use are triggered by the VRPN communications protocol used by the Camera System. Whenever the Client receives a new packet of data from the Camera System the callback will be triggered. ==Registering a Callback== Before we can do anything we need to set up a callback that executes when new data is present. :1. Use the VRPN Library to create a ''Connection'' and ''Tracker_Remote'' object pointers (code in ''vrpn.cpp''): <blockquote> <code> <pre> vrpn_Connection *connection; vrpn_Tracker_Remote *trackerHand; vrpn_Tracker_Remote *tracker; vrpn_Tracker_Remote *tracker2; vrpn_Tracker_Remote *tracker3; vrpn_Tracker_Remote *tracker4; </pre> </code> </blockquote> ::'''Note:''' We need a ''Tracker_Remote'' object for each constellation we want to track (Hand and each Crazyflie in the Swarm) :2. Now we create a function to: :#Register the connection to the Server computer :#Assign each ''Tracker_Remote'' object to a valid constellation name on the Server computer :#Link that constellation to a callback (code in ''vrpn.cpp''): <blockquote> <code> <pre> void vrpn_init(std::string connectionName, void (*callbackHand)(void*, const vrpn_TRACKERCB), void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback3)(void*, const vrpn_TRACKERCB), void (*callback4)(void*, const vrpn_TRACKERCB), char *key) { connection = vrpn_get_connection_by_name(connectionName.c_str()); #if USE_HAND trackerHand = new vrpn_Tracker_Remote("hand", connection); #endif tracker = new vrpn_Tracker_Remote("Crazyflie21", connection); tracker2 = new vrpn_Tracker_Remote("Crazyflie2", connection); tracker3 = new vrpn_Tracker_Remote("Crazyflie22", connection); tracker4 = new vrpn_Tracker_Remote("Crazyflie23", connection); #if USE_HAND trackerHand->register_change_handler(0, callbackHand); #endif tracker->register_change_handler(0, callback); tracker2->register_change_handler(0, callback2); tracker3->register_change_handler(0, callback3); tracker4->register_change_handler(0, callback4); usleep(2000); } </pre> </code> </blockquote> ::'''Note 1:''' We pass in the following as inputs to the function: ::*''string connectionName'' is the '''IP address''' of the Computer running the Camera System ::*A callback pointer for each constellation we want to track (These will be established in the [[#Using a Callback|Using a Callback]] section) ::'''Note 2:''' Notice the names of each ''tracker'' '''match the names of the constellations''' in the Camera System Software (shown below): ::[[Image:TrackingToolsCrazyflieConstellationZeroing.png|800px]] ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 040fb27438f015cc7329480c744788fb59e0c197 148 146 2016-07-27T19:02:03Z Jnoronha 3 Added full callback example wikitext text/x-wiki A callback is a segment of code that will run only when a certain condition is satisfied. For the Swarm Platform, the callbacks we use are triggered by the VRPN communications protocol used by the Camera System. Whenever the Client receives a new packet of data from the Camera System the callback will be triggered. ==Registering a Callback== Before we can do anything we need to set up a callback that executes when new data is present. :1. Use the VRPN Library to create a ''Connection'' and ''Tracker_Remote'' object pointers (code in ''vrpn.cpp''): <blockquote> <code> <pre> vrpn_Connection *connection; vrpn_Tracker_Remote *trackerHand; vrpn_Tracker_Remote *tracker; vrpn_Tracker_Remote *tracker2; vrpn_Tracker_Remote *tracker3; vrpn_Tracker_Remote *tracker4; </pre> </code> </blockquote> ::'''Note:''' We need a ''Tracker_Remote'' object for each constellation we want to track (Hand and each Crazyflie in the Swarm) :2. Now we create a function to (code in ''vrpn.cpp''): :#Register the connection to the Server computer :#Assign each ''Tracker_Remote'' object to a valid constellation name on the Server computer :#Link that constellation to a callback <blockquote> <code> <pre> void vrpn_init(std::string connectionName, void (*callbackHand)(void*, const vrpn_TRACKERCB), void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback3)(void*, const vrpn_TRACKERCB), void (*callback4)(void*, const vrpn_TRACKERCB), char *key) { connection = vrpn_get_connection_by_name(connectionName.c_str()); #if USE_HAND trackerHand = new vrpn_Tracker_Remote("hand", connection); #endif tracker = new vrpn_Tracker_Remote("Crazyflie21", connection); tracker2 = new vrpn_Tracker_Remote("Crazyflie2", connection); tracker3 = new vrpn_Tracker_Remote("Crazyflie22", connection); tracker4 = new vrpn_Tracker_Remote("Crazyflie23", connection); #if USE_HAND trackerHand->register_change_handler(0, callbackHand); #endif tracker->register_change_handler(0, callback); tracker2->register_change_handler(0, callback2); tracker3->register_change_handler(0, callback3); tracker4->register_change_handler(0, callback4); usleep(2000); } </pre> </code> </blockquote> ::'''Note 1:''' We pass in the following as inputs to the function: ::*''string connectionName'' is the "'''IP address:Port'''" of the Computer running the Camera System ::**(You can see the ''VRPN Broadcast Port'' used in the on the middle-right pane called ''Streaming Properties'') ::*A callback pointer for each constellation we want to track (These will be established in the [[:Callbacks#Using a Callback in the Swarm Client|Using a Callback]] section) ::'''Note 2:''' Notice the names of each ''tracker'' '''match the names of the constellations''' in the Camera System Software (shown below): ::[[Image:TrackingToolsCrazyflieConstellationParams.png|800px]] ==Using a Callback in the Swarm Client== The Swarm Client needs to re-establish the connection to the VRPN server for each test. ===Initializing the Callbacks=== :1. Create the Callback Objects (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> void VRPN_CALLBACK handle_hand(void*, const vrpn_TRACKERCB t); void VRPN_CALLBACK handle_pos(void*, const vrpn_TRACKERCB t); //Old name scheme (represents Callback for Crazyflie1) void VRPN_CALLBACK handle_Crazyflie2(void*, const vrpn_TRACKERCB t); void VRPN_CALLBACK handle_Crazyflie3(void*, const vrpn_TRACKERCB t); void VRPN_CALLBACK handle_Crazyflie4(void*, const vrpn_TRACKERCB t); </pre> </code> </blockquote> :2. [[:Callbacks#Registering a Callback|Register the connection]] and constellations to the Callbacks (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> #if NUM_QUADS == 1 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, NULL, NULL, NULL, NULL); #elif NUM_QUADS == 2 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, handle_Crazyflie2, NULL, NULL, NULL); #elif NUM_QUADS == 3 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, handle_Crazyflie2, handle_Crazyflie3, NULL, NULL); #elif NUM_QUADS == 4 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, handle_Crazyflie2, handle_Crazyflie3, handle_Crazyflie4, NULL); #endif </pre> </code> </blockquote> ::'''Note:''' If we don't want to track a certain Crazyflie (i.e. we only want to fly 2 Crazyflies) we can just pass <code>NULL</code> into the init function for the callbacks we don't care about. ===Trigger a Callback=== ===Full Callback Example=== Below is a full Callback example for Crazyflie1: <blockquote> <code> <pre> #if NUM_QUADS >= 1 void VRPN_CALLBACK handle_pos(void*, const vrpn_TRACKERCB t) { //cout << "First Callback" << endl; if(vrpnPacketBackup1 < 2) //If VRPN Buffer does NOT have old packets stored up, run main code { loopTime1Start = cflieCopter1->currentTime() - initTime1; loopTime1Delta = loopTime1Start - loopTime1Prev; //Calculates time difference between each loop start loopTime1Prev = loopTime1Start; vrpnPacketTime1 = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnPacketDelta1 = vrpnPacketTime1 - vrpnPacketTime1Prev; //Calculates time between VRPN Data Packets (almost always 0.01 sec) vrpnPacketTime1Prev = vrpnPacketTime1; vrpnPacketBackup1 = ceil(loopTime1Delta/vrpnPacketDelta1); //Calculates estimated # of packets built up in VRPN buffer. controllerSetAllDt(&pidCtrl1, vrpnPacketDelta1); //Variable dt for controller based on time between packets | vrpnPacketDelta1 #if NUM_QUADS == 2 cflieCopter2->cheat_process_packets(); #elif NUM_QUADS == 3 cflieCopter3->cheat_process_packets(); #elif NUM_QUADS == 4 cflieCopter2->cheat_process_packets(); #endif crRadio1->clearPackets(); //Clears the USB Radio Buffer before switching Radio channels crRadio1->setChannel( cflieCopter1->radioChannel() ); frameCount++; // Get the euler angles q_vec_type euler; q_to_euler(euler, t.quat); xPosition1 = t.pos[0]; yPosition1 = t.pos[1]; //Stores X, Y, and Z Position for use in other Callbacks (external) zPosition1 = -t.pos[2] + 0.05; #if USE_PRINTOUT cout << "PID Radio 1" << endl << endl; #endif #if 0 //Old way of storing Camera Data (most of it was unnecessary) UNUSED cfliePitch = cflieCopter1->pitch(); cflieRoll = cflieCopter1->roll(); cflieYaw = cflieCopter1->yaw(); cflieThrust = cflieCopter1->thrust(); /* Legend for Camera Data Packet * Position * x t.pos[0] * y t.pos[1] * z t.pos[2] * * Orientation * yaw euler[0] Rotation * pitch euler[1] East-West movement * roll euler[2] North-South movement * Euler's range goes from -pi : +pi */ QUAD quad; quad.vrpnNow = 0; vrpn_data_t *vrpnData; vrpnData = (vrpn_data_t*) malloc(sizeof(vrpn_data_t)); vrpnData->usec = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnData->x = t.pos[0]; vrpnData->y = t.pos[1]; vrpnData->z = -t.pos[2] + 0.05; //Higher Altitude = Negative z //Added Offset for floor below camera system origin vrpnData->yaw = euler[0]; vrpnData->pitch = euler[1]; vrpnData->roll = euler[2]; quad.vrpnPrev = quad.vrpnNow; if (quad.vrpnNow == 0) { quad.vrpnPrev = 0; quad.vrpnTime0 = vrpnData->usec; quad.vrpnNow = vrpnData->usec; } else { quad.vrpnNow = vrpnData->usec - quad.vrpnTime0; } #endif //END UNUSED //==============YAW CORRECTION========================= (IMPORTANT!!!: YAW CONTROLLER INPUT IS INVERTED IN simple.cpp FILE***) camYawDeg1 = -(euler[0] * 57.2958); //Getting Camera Yaw (Converts From Radians TO Degrees) quadYaw1 = cflieCopter1->yaw(); //Getting Crazyflie Yaw if (frameCount == 50) { if (camYawDeg1 < 0.0) camYawDeg1Off = camYawDeg1 + 360.0; //Converts from +-180 to full 360 degree form else camYawDeg1Off = camYawDeg1; if(quadYaw1 < 0.0) quadYaw1Off = quadYaw1 + 360.0; else quadYaw1Off = quadYaw1; yawDifference1 = quadYaw1Off - camYawDeg1Off; cout << "Yaw1 Offset Taken: " << yawDifference1 << endl; } correctedYaw1 = camYawDeg1 + yawDifference1; if(correctedYaw1 > 180.0) correctedYaw1 -= 360.0; else if(correctedYaw1 < -180.0) correctedYaw1 += 360.0; //===============END YAW CORRECTION========================= #if USE_PRINTOUT cout << "X: " << t.pos[0] << endl; cout << "Y: " << t.pos[1] << endl; cout << "Z: " << -t.pos[2] + 0.05 << endl; // cout << "Quad Yaw: " << cflieCopter1->yaw() << endl; // cout << "Camera Yaw: " << camYawDeg1 << endl; // cout << "Yaw Offset: " << yawDifference1 << endl; // cout << "New Desired Yaw: " << yawDesired1 << endl; cout << "Frame Count: " << frameCount << endl; #endif #if USE_KEYBOARD if (cflieCopter1->m_enumFlightMode == LANDING_MODE) //Landing Mode { //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError1 = cos(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) - sin(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); // yError1 = sin(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) + cos(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, -0.4, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); takeOff1 = 0; } else if (cflieCopter1->m_enumFlightMode == MIRROR_MODE) { //Acts as Master xPositionDesired1 = -0.012; yPositionDesired1 = -0.200; zPositionDesired1 = 0.75; if( loopTime1Start - lastTime > 4.0 ) //Creates a 'Step' by changing setpoint every 4 seconds { toggle = !toggle; lastTime = loopTime1Start; } if(toggle) { xStepPositionError1 = xPositionDesired1 - xPosition1; yStepPositionError1 = yPositionDesired1 - yPosition1; controllerSetXYError(&pidCtrl1, xStepPositionError1, yStepPositionError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); } else //Shifts current x and y setpoint 0.65 meters { xStepPositionError1 = (xPositionDesired1 + 0.65) - xPosition1; yStepPositionError1 = (yPositionDesired1 + 0.65) - yPosition1; controllerSetXYError(&pidCtrl1, xStepPositionError1, yStepPositionError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1 + 0.65, yPositionDesired1 + 0.65, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); //cout << "Toggled!" << endl; } } else if (cflieCopter1->m_enumFlightMode == TAKEOFF_MODE) { //correctedYaw1 //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError1 = cos(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) - sin(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); // yError1 = sin(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) + cos(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); } else if (cflieCopter1->m_enumFlightMode == HAND_MODE) { //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError1 = cos(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) - sin(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); // yError1 = sin(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) + cos(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); xError1 = (xPositionHand - 0.5) - xPosition1; yError1 = (yPositionHand + 0.5) - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); } else if(flap){ //Flap Mode (OBSOLETE) // cflieCopter1->setThrust(20000); // cflieCopter2->setThrust(20000); //45000 Thrust of Crazyflie2.0 to match Crazyflie1.0 // cflieCopter2->setYaw(90); // lastTime = cflieCopter2->currentTime(); curTime = cflieCopter2->currentTime(); if( curTime - lastTime > 1.0 ) { toggle = !toggle; lastTime = curTime; } if( toggle ){ cflieCopter1->setThrust( 20000 ); printf("Low %.3lf ", curTime); } else { cflieCopter1->setThrust( 40000 ); printf("High %.3lf ", curTime); } } else if(cflieCopter1->m_enumFlightMode == GROUNDED_MODE){ controllerResetAllPID(&pidCtrl1); rollControlOutput1 = 0; pitchControlOutput1 = 0; yawControlOutput1 = 0; thrustControlOutput1 = 0; } else{ //Emergency Case (Should never happen) controllerResetAllPID(&pidCtrl1); rollControlOutput1 = 0; pitchControlOutput1 = 0; yawControlOutput1 = 0; thrustControlOutput1 = 0; } #else //If keyboard input NOT enabled then just run default Controller controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], -t.pos[2], correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); #endif RunCrazyflie(crRadio1, cflieCopter1, rollControlOutput1, pitchControlOutput1, yawControlOutput1, thrustControlOutput1); #if USE_LOGGING #if USE_BASIC_LOGGING fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); // fprintf(out1, "\n"); #else //FULL LOGGING ROUTINE (***CAUSES MAJOR BOTTLENECK IN CODE TIMING THE MORE VARIABLES YOU LOG***) fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t%.3f\t\t%.3f\t\t%.3f", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, pitchControlOutput1, rollControlOutput1, yawControlOutput1, thrustControlOutput1, cflieCopter1->radioRSSI(), euler[0], euler[1], euler[2], cflieCopter1->motor1(), cflieCopter1->motor2(), cflieCopter1->motor3(), cflieCopter1->motor4(), cflieCopter1->gyroX(), cflieCopter1->gyroY(), cflieCopter1->gyroZ()); // fprintf(out1, "\n"); #endif #endif #if 0 //(UNUSED) if (tcp_client_ON) { readMulticast(); //(argc < 1 = Listen Mode) // runTCPClient(); } #endif //cout << "PID Radio 2" << endl << endl; loopTime1End = cflieCopter1->currentTime() - initTime1; loopTime1 = loopTime1End - loopTime1Start; } else if(vrpnPacketBackup1 < 0){ //Failsafe so can't go below 0 (should never happen) | || (vrpnPacketBackup1 > 20)? vrpnPacketBackup1 = 0; } else if(vrpnPacketBackup1 >= 2){ vrpnPacketBackup1 --; // cout << "VRPN Packet Backup 1 Detected: " << vrpnPacketBackup1 << endl; }//End Packet Backup If check } //End Callback 1 </pre> </code> </blockquote> ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 2cd4f630c29ebfca0cece43d09c3c064bdfcf945 149 148 2016-07-27T19:06:14Z Jnoronha 3 /* Using a Callback in the Swarm Client */ changed the full callback example to a lvl 2 heading wikitext text/x-wiki A callback is a segment of code that will run only when a certain condition is satisfied. For the Swarm Platform, the callbacks we use are triggered by the VRPN communications protocol used by the Camera System. Whenever the Client receives a new packet of data from the Camera System the callback will be triggered. ==Registering a Callback== Before we can do anything we need to set up a callback that executes when new data is present. :1. Use the VRPN Library to create a ''Connection'' and ''Tracker_Remote'' object pointers (code in ''vrpn.cpp''): <blockquote> <code> <pre> vrpn_Connection *connection; vrpn_Tracker_Remote *trackerHand; vrpn_Tracker_Remote *tracker; vrpn_Tracker_Remote *tracker2; vrpn_Tracker_Remote *tracker3; vrpn_Tracker_Remote *tracker4; </pre> </code> </blockquote> ::'''Note:''' We need a ''Tracker_Remote'' object for each constellation we want to track (Hand and each Crazyflie in the Swarm) :2. Now we create a function to (code in ''vrpn.cpp''): :#Register the connection to the Server computer :#Assign each ''Tracker_Remote'' object to a valid constellation name on the Server computer :#Link that constellation to a callback <blockquote> <code> <pre> void vrpn_init(std::string connectionName, void (*callbackHand)(void*, const vrpn_TRACKERCB), void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback3)(void*, const vrpn_TRACKERCB), void (*callback4)(void*, const vrpn_TRACKERCB), char *key) { connection = vrpn_get_connection_by_name(connectionName.c_str()); #if USE_HAND trackerHand = new vrpn_Tracker_Remote("hand", connection); #endif tracker = new vrpn_Tracker_Remote("Crazyflie21", connection); tracker2 = new vrpn_Tracker_Remote("Crazyflie2", connection); tracker3 = new vrpn_Tracker_Remote("Crazyflie22", connection); tracker4 = new vrpn_Tracker_Remote("Crazyflie23", connection); #if USE_HAND trackerHand->register_change_handler(0, callbackHand); #endif tracker->register_change_handler(0, callback); tracker2->register_change_handler(0, callback2); tracker3->register_change_handler(0, callback3); tracker4->register_change_handler(0, callback4); usleep(2000); } </pre> </code> </blockquote> ::'''Note 1:''' We pass in the following as inputs to the function: ::*''string connectionName'' is the "'''IP address:Port'''" of the Computer running the Camera System ::**(You can see the ''VRPN Broadcast Port'' used in the on the middle-right pane called ''Streaming Properties'') ::*A callback pointer for each constellation we want to track (These will be established in the [[:Callbacks#Using a Callback in the Swarm Client|Using a Callback]] section) ::'''Note 2:''' Notice the names of each ''tracker'' '''match the names of the constellations''' in the Camera System Software (shown below): ::[[Image:TrackingToolsCrazyflieConstellationParams.png|800px]] ==Using a Callback in the Swarm Client== The Swarm Client needs to re-establish the connection to the VRPN server for each test. ===Initializing the Callbacks=== :1. Create the Callback Objects (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> void VRPN_CALLBACK handle_hand(void*, const vrpn_TRACKERCB t); void VRPN_CALLBACK handle_pos(void*, const vrpn_TRACKERCB t); //Old name scheme (represents Callback for Crazyflie1) void VRPN_CALLBACK handle_Crazyflie2(void*, const vrpn_TRACKERCB t); void VRPN_CALLBACK handle_Crazyflie3(void*, const vrpn_TRACKERCB t); void VRPN_CALLBACK handle_Crazyflie4(void*, const vrpn_TRACKERCB t); </pre> </code> </blockquote> :2. [[:Callbacks#Registering a Callback|Register the connection]] and constellations to the Callbacks (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> #if NUM_QUADS == 1 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, NULL, NULL, NULL, NULL); #elif NUM_QUADS == 2 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, handle_Crazyflie2, NULL, NULL, NULL); #elif NUM_QUADS == 3 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, handle_Crazyflie2, handle_Crazyflie3, NULL, NULL); #elif NUM_QUADS == 4 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, handle_Crazyflie2, handle_Crazyflie3, handle_Crazyflie4, NULL); #endif </pre> </code> </blockquote> ::'''Note:''' If we don't want to track a certain Crazyflie (i.e. we only want to fly 2 Crazyflies) we can just pass <code>NULL</code> into the init function for the callbacks we don't care about. ===Trigger a Callback=== :3. Start the mainloop: <code>vrpn_go()</code> (code in ''vrpn.cpp''): <blockquote> <code> <pre> void vrpn_go() { int i = 0; //for ending the while loop while(!i){ //1 replace 'i<20000' when done testing ****** readKeyboard(); nearGround(); #if USE_HAND updateHand(); #endif loopTimeTotalStart = cflieCopter1->currentTime() - initTime1; loopTimeTotalDelta = loopTimeTotalStart - loopTimeTotalPrev; loopTimeTotalPrev = loopTimeTotalStart; connection->mainloop(); #if USE_HAND trackerHand->mainloop(); #endif tracker->mainloop(); tracker2->mainloop(); tracker3->mainloop(); tracker4->mainloop(); usleep(200); //Was 200 //Testing Routines //i++; //nonblock(0); nonblock(1); usleep(1); i = kbhit(); //keyboard hit (state change) if (i!=0) { keystroke_now = fgetc(stdin); if (keystroke_now == 'q') i=1; else{ i=0; } //fprintf(stderr,"%d ",i); } }//END WHILE if(keystroke_now == 'q'){ cout << "Program Forced End" << endl; } loopTimeTotalEnd = cflieCopter1->currentTime() - initTime1; loopTimeTotal = loopTimeTotalEnd - loopTimeTotalStart; } //END VRPN GO </pre> </code> </blockquote> ==Full Callback Example== Below is a full Callback example for Crazyflie1: <blockquote> <code> <pre> #if NUM_QUADS >= 1 void VRPN_CALLBACK handle_pos(void*, const vrpn_TRACKERCB t) { //cout << "First Callback" << endl; if(vrpnPacketBackup1 < 2) //If VRPN Buffer does NOT have old packets stored up, run main code { loopTime1Start = cflieCopter1->currentTime() - initTime1; loopTime1Delta = loopTime1Start - loopTime1Prev; //Calculates time difference between each loop start loopTime1Prev = loopTime1Start; vrpnPacketTime1 = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnPacketDelta1 = vrpnPacketTime1 - vrpnPacketTime1Prev; //Calculates time between VRPN Data Packets (almost always 0.01 sec) vrpnPacketTime1Prev = vrpnPacketTime1; vrpnPacketBackup1 = ceil(loopTime1Delta/vrpnPacketDelta1); //Calculates estimated # of packets built up in VRPN buffer. controllerSetAllDt(&pidCtrl1, vrpnPacketDelta1); //Variable dt for controller based on time between packets | vrpnPacketDelta1 #if NUM_QUADS == 2 cflieCopter2->cheat_process_packets(); #elif NUM_QUADS == 3 cflieCopter3->cheat_process_packets(); #elif NUM_QUADS == 4 cflieCopter2->cheat_process_packets(); #endif crRadio1->clearPackets(); //Clears the USB Radio Buffer before switching Radio channels crRadio1->setChannel( cflieCopter1->radioChannel() ); frameCount++; // Get the euler angles q_vec_type euler; q_to_euler(euler, t.quat); xPosition1 = t.pos[0]; yPosition1 = t.pos[1]; //Stores X, Y, and Z Position for use in other Callbacks (external) zPosition1 = -t.pos[2] + 0.05; #if USE_PRINTOUT cout << "PID Radio 1" << endl << endl; #endif #if 0 //Old way of storing Camera Data (most of it was unnecessary) UNUSED cfliePitch = cflieCopter1->pitch(); cflieRoll = cflieCopter1->roll(); cflieYaw = cflieCopter1->yaw(); cflieThrust = cflieCopter1->thrust(); /* Legend for Camera Data Packet * Position * x t.pos[0] * y t.pos[1] * z t.pos[2] * * Orientation * yaw euler[0] Rotation * pitch euler[1] East-West movement * roll euler[2] North-South movement * Euler's range goes from -pi : +pi */ QUAD quad; quad.vrpnNow = 0; vrpn_data_t *vrpnData; vrpnData = (vrpn_data_t*) malloc(sizeof(vrpn_data_t)); vrpnData->usec = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnData->x = t.pos[0]; vrpnData->y = t.pos[1]; vrpnData->z = -t.pos[2] + 0.05; //Higher Altitude = Negative z //Added Offset for floor below camera system origin vrpnData->yaw = euler[0]; vrpnData->pitch = euler[1]; vrpnData->roll = euler[2]; quad.vrpnPrev = quad.vrpnNow; if (quad.vrpnNow == 0) { quad.vrpnPrev = 0; quad.vrpnTime0 = vrpnData->usec; quad.vrpnNow = vrpnData->usec; } else { quad.vrpnNow = vrpnData->usec - quad.vrpnTime0; } #endif //END UNUSED //==============YAW CORRECTION========================= (IMPORTANT!!!: YAW CONTROLLER INPUT IS INVERTED IN simple.cpp FILE***) camYawDeg1 = -(euler[0] * 57.2958); //Getting Camera Yaw (Converts From Radians TO Degrees) quadYaw1 = cflieCopter1->yaw(); //Getting Crazyflie Yaw if (frameCount == 50) { if (camYawDeg1 < 0.0) camYawDeg1Off = camYawDeg1 + 360.0; //Converts from +-180 to full 360 degree form else camYawDeg1Off = camYawDeg1; if(quadYaw1 < 0.0) quadYaw1Off = quadYaw1 + 360.0; else quadYaw1Off = quadYaw1; yawDifference1 = quadYaw1Off - camYawDeg1Off; cout << "Yaw1 Offset Taken: " << yawDifference1 << endl; } correctedYaw1 = camYawDeg1 + yawDifference1; if(correctedYaw1 > 180.0) correctedYaw1 -= 360.0; else if(correctedYaw1 < -180.0) correctedYaw1 += 360.0; //===============END YAW CORRECTION========================= #if USE_PRINTOUT cout << "X: " << t.pos[0] << endl; cout << "Y: " << t.pos[1] << endl; cout << "Z: " << -t.pos[2] + 0.05 << endl; // cout << "Quad Yaw: " << cflieCopter1->yaw() << endl; // cout << "Camera Yaw: " << camYawDeg1 << endl; // cout << "Yaw Offset: " << yawDifference1 << endl; // cout << "New Desired Yaw: " << yawDesired1 << endl; cout << "Frame Count: " << frameCount << endl; #endif #if USE_KEYBOARD if (cflieCopter1->m_enumFlightMode == LANDING_MODE) //Landing Mode { //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError1 = cos(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) - sin(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); // yError1 = sin(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) + cos(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, -0.4, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); takeOff1 = 0; } else if (cflieCopter1->m_enumFlightMode == MIRROR_MODE) { //Acts as Master xPositionDesired1 = -0.012; yPositionDesired1 = -0.200; zPositionDesired1 = 0.75; if( loopTime1Start - lastTime > 4.0 ) //Creates a 'Step' by changing setpoint every 4 seconds { toggle = !toggle; lastTime = loopTime1Start; } if(toggle) { xStepPositionError1 = xPositionDesired1 - xPosition1; yStepPositionError1 = yPositionDesired1 - yPosition1; controllerSetXYError(&pidCtrl1, xStepPositionError1, yStepPositionError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); } else //Shifts current x and y setpoint 0.65 meters { xStepPositionError1 = (xPositionDesired1 + 0.65) - xPosition1; yStepPositionError1 = (yPositionDesired1 + 0.65) - yPosition1; controllerSetXYError(&pidCtrl1, xStepPositionError1, yStepPositionError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1 + 0.65, yPositionDesired1 + 0.65, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); //cout << "Toggled!" << endl; } } else if (cflieCopter1->m_enumFlightMode == TAKEOFF_MODE) { //correctedYaw1 //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError1 = cos(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) - sin(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); // yError1 = sin(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) + cos(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); } else if (cflieCopter1->m_enumFlightMode == HAND_MODE) { //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError1 = cos(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) - sin(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); // yError1 = sin(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) + cos(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); xError1 = (xPositionHand - 0.5) - xPosition1; yError1 = (yPositionHand + 0.5) - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); } else if(flap){ //Flap Mode (OBSOLETE) // cflieCopter1->setThrust(20000); // cflieCopter2->setThrust(20000); //45000 Thrust of Crazyflie2.0 to match Crazyflie1.0 // cflieCopter2->setYaw(90); // lastTime = cflieCopter2->currentTime(); curTime = cflieCopter2->currentTime(); if( curTime - lastTime > 1.0 ) { toggle = !toggle; lastTime = curTime; } if( toggle ){ cflieCopter1->setThrust( 20000 ); printf("Low %.3lf ", curTime); } else { cflieCopter1->setThrust( 40000 ); printf("High %.3lf ", curTime); } } else if(cflieCopter1->m_enumFlightMode == GROUNDED_MODE){ controllerResetAllPID(&pidCtrl1); rollControlOutput1 = 0; pitchControlOutput1 = 0; yawControlOutput1 = 0; thrustControlOutput1 = 0; } else{ //Emergency Case (Should never happen) controllerResetAllPID(&pidCtrl1); rollControlOutput1 = 0; pitchControlOutput1 = 0; yawControlOutput1 = 0; thrustControlOutput1 = 0; } #else //If keyboard input NOT enabled then just run default Controller controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], -t.pos[2], correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); #endif RunCrazyflie(crRadio1, cflieCopter1, rollControlOutput1, pitchControlOutput1, yawControlOutput1, thrustControlOutput1); #if USE_LOGGING #if USE_BASIC_LOGGING fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); // fprintf(out1, "\n"); #else //FULL LOGGING ROUTINE (***CAUSES MAJOR BOTTLENECK IN CODE TIMING THE MORE VARIABLES YOU LOG***) fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t%.3f\t\t%.3f\t\t%.3f", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, pitchControlOutput1, rollControlOutput1, yawControlOutput1, thrustControlOutput1, cflieCopter1->radioRSSI(), euler[0], euler[1], euler[2], cflieCopter1->motor1(), cflieCopter1->motor2(), cflieCopter1->motor3(), cflieCopter1->motor4(), cflieCopter1->gyroX(), cflieCopter1->gyroY(), cflieCopter1->gyroZ()); // fprintf(out1, "\n"); #endif #endif #if 0 //(UNUSED) if (tcp_client_ON) { readMulticast(); //(argc < 1 = Listen Mode) // runTCPClient(); } #endif //cout << "PID Radio 2" << endl << endl; loopTime1End = cflieCopter1->currentTime() - initTime1; loopTime1 = loopTime1End - loopTime1Start; } else if(vrpnPacketBackup1 < 0){ //Failsafe so can't go below 0 (should never happen) | || (vrpnPacketBackup1 > 20)? vrpnPacketBackup1 = 0; } else if(vrpnPacketBackup1 >= 2){ vrpnPacketBackup1 --; // cout << "VRPN Packet Backup 1 Detected: " << vrpnPacketBackup1 << endl; }//End Packet Backup If check } //End Callback 1 </pre> </code> </blockquote> ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> b4be15ef64d405a0347a7dd9781751fbaad47b88 150 149 2016-07-27T19:27:18Z Jnoronha 3 /* Using a Callback in the Swarm Client */ added flowchart and finished wikitext text/x-wiki A callback is a segment of code that will run only when a certain condition is satisfied. For the Swarm Platform, the callbacks we use are triggered by the VRPN communications protocol used by the Camera System. Whenever the Client receives a new packet of data from the Camera System the callback will be triggered. ==Registering a Callback== Before we can do anything we need to set up a callback that executes when new data is present. :1. Use the VRPN Library to create a ''Connection'' and ''Tracker_Remote'' object pointers (code in ''vrpn.cpp''): <blockquote> <code> <pre> vrpn_Connection *connection; vrpn_Tracker_Remote *trackerHand; vrpn_Tracker_Remote *tracker; vrpn_Tracker_Remote *tracker2; vrpn_Tracker_Remote *tracker3; vrpn_Tracker_Remote *tracker4; </pre> </code> </blockquote> ::'''Note:''' We need a ''Tracker_Remote'' object for each constellation we want to track (Hand and each Crazyflie in the Swarm) :2. Now we create a function to (code in ''vrpn.cpp''): :#Register the connection to the Server computer :#Assign each ''Tracker_Remote'' object to a valid constellation name on the Server computer :#Link that constellation to a callback <blockquote> <code> <pre> void vrpn_init(std::string connectionName, void (*callbackHand)(void*, const vrpn_TRACKERCB), void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback3)(void*, const vrpn_TRACKERCB), void (*callback4)(void*, const vrpn_TRACKERCB), char *key) { connection = vrpn_get_connection_by_name(connectionName.c_str()); #if USE_HAND trackerHand = new vrpn_Tracker_Remote("hand", connection); #endif tracker = new vrpn_Tracker_Remote("Crazyflie21", connection); tracker2 = new vrpn_Tracker_Remote("Crazyflie2", connection); tracker3 = new vrpn_Tracker_Remote("Crazyflie22", connection); tracker4 = new vrpn_Tracker_Remote("Crazyflie23", connection); #if USE_HAND trackerHand->register_change_handler(0, callbackHand); #endif tracker->register_change_handler(0, callback); tracker2->register_change_handler(0, callback2); tracker3->register_change_handler(0, callback3); tracker4->register_change_handler(0, callback4); usleep(2000); } </pre> </code> </blockquote> ::'''Note 1:''' We pass in the following as inputs to the function: ::*''string connectionName'' is the "'''IP address:Port'''" of the Computer running the Camera System ::**(You can see the ''VRPN Broadcast Port'' used in the on the middle-right pane called ''Streaming Properties'') ::*A callback pointer for each constellation we want to track (These will be established in the [[:Callbacks#Using a Callback in the Swarm Client|Using a Callback]] section) ::'''Note 2:''' Notice the names of each ''tracker'' '''match the names of the constellations''' in the Camera System Software (shown below): ::[[Image:TrackingToolsCrazyflieConstellationParams.png|800px]] ==Using a Callback in the Swarm Client== The Swarm Client needs to re-establish the connection to the VRPN server for each test. ===Initializing the Callbacks=== :1. Create the Callback Objects (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> void VRPN_CALLBACK handle_hand(void*, const vrpn_TRACKERCB t); void VRPN_CALLBACK handle_pos(void*, const vrpn_TRACKERCB t); //Old name scheme (represents Callback for Crazyflie1) void VRPN_CALLBACK handle_Crazyflie2(void*, const vrpn_TRACKERCB t); void VRPN_CALLBACK handle_Crazyflie3(void*, const vrpn_TRACKERCB t); void VRPN_CALLBACK handle_Crazyflie4(void*, const vrpn_TRACKERCB t); </pre> </code> </blockquote> :2. [[:Callbacks#Registering a Callback|Register the connection]] and constellations to the Callbacks (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> #if NUM_QUADS == 1 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, NULL, NULL, NULL, NULL); #elif NUM_QUADS == 2 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, handle_Crazyflie2, NULL, NULL, NULL); #elif NUM_QUADS == 3 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, handle_Crazyflie2, handle_Crazyflie3, NULL, NULL); #elif NUM_QUADS == 4 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, handle_Crazyflie2, handle_Crazyflie3, handle_Crazyflie4, NULL); #endif </pre> </code> </blockquote> ::'''Note:''' If we don't want to track a certain Crazyflie (i.e. we only want to fly 2 Crazyflies) we can just pass <code>NULL</code> into the init function for the callbacks we don't care about. ===Calling a Callback=== :3. Start the mainloop: <code>vrpn_go()</code> (code in ''vrpn.cpp'') (function called in ''eris_vrpn.cpp'') ::*A flowchart of the vrpn_go() function: [[Image:VRPNGO.png|500px]] ::*Full vrpn_go() code (code in ''vrpn.cpp''): <blockquote> <code> <pre> void vrpn_go() { int i = 0; //for ending the while loop while(!i){ readKeyboard(); //Triggers actions based on key value read nearGround(); #if USE_HAND updateHand(); //Checks for Valid Hand Gestures #endif //Calculates Total Loop Timing loopTimeTotalStart = cflieCopter1->currentTime() - initTime1; loopTimeTotalDelta = loopTimeTotalStart - loopTimeTotalPrev; loopTimeTotalPrev = loopTimeTotalStart; connection->mainloop(); //Pings the Server Connection to see if still alive #if USE_HAND trackerHand->mainloop(); //Checks if Hand constellation has new data (runs callback if true) #endif tracker->mainloop(); //IMPORTANT: Checks if Crazyflie1 constellation has new data (runs callback if true) tracker2->mainloop(); //Same... tracker3->mainloop(); tracker4->mainloop(); usleep(200); //Was 200 nonblock(1); usleep(1); i = kbhit(); //keyboard hit (state change) if (i!=0) { keystroke_now = fgetc(stdin); //Stores key value pressed if (keystroke_now == 'q') i=1; else{ i=0; } //fprintf(stderr,"%d ",i); } }//END WHILE if(keystroke_now == 'q'){ cout << "Program Forced End" << endl; } loopTimeTotalEnd = cflieCopter1->currentTime() - initTime1; loopTimeTotal = loopTimeTotalEnd - loopTimeTotalStart; } //END VRPN GO </pre> </code> </blockquote> ::'''Note:''' The most important part of this is the <code>tracker->mainloop();</code> functions. These functions are what calls the Callback if there is new data waiting!! ::You can see an example of the code that is executed whenever the [[:Callbacks#Full Callback Example|callback is triggered]] ==Full Callback Example== Below is a full Callback example for Crazyflie1: <blockquote> <code> <pre> #if NUM_QUADS >= 1 void VRPN_CALLBACK handle_pos(void*, const vrpn_TRACKERCB t) { //cout << "First Callback" << endl; if(vrpnPacketBackup1 < 2) //If VRPN Buffer does NOT have old packets stored up, run main code { loopTime1Start = cflieCopter1->currentTime() - initTime1; loopTime1Delta = loopTime1Start - loopTime1Prev; //Calculates time difference between each loop start loopTime1Prev = loopTime1Start; vrpnPacketTime1 = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnPacketDelta1 = vrpnPacketTime1 - vrpnPacketTime1Prev; //Calculates time between VRPN Data Packets (almost always 0.01 sec) vrpnPacketTime1Prev = vrpnPacketTime1; vrpnPacketBackup1 = ceil(loopTime1Delta/vrpnPacketDelta1); //Calculates estimated # of packets built up in VRPN buffer. controllerSetAllDt(&pidCtrl1, vrpnPacketDelta1); //Variable dt for controller based on time between packets | vrpnPacketDelta1 #if NUM_QUADS == 2 cflieCopter2->cheat_process_packets(); #elif NUM_QUADS == 3 cflieCopter3->cheat_process_packets(); #elif NUM_QUADS == 4 cflieCopter2->cheat_process_packets(); #endif crRadio1->clearPackets(); //Clears the USB Radio Buffer before switching Radio channels crRadio1->setChannel( cflieCopter1->radioChannel() ); frameCount++; // Get the euler angles q_vec_type euler; q_to_euler(euler, t.quat); xPosition1 = t.pos[0]; yPosition1 = t.pos[1]; //Stores X, Y, and Z Position for use in other Callbacks (external) zPosition1 = -t.pos[2] + 0.05; #if USE_PRINTOUT cout << "PID Radio 1" << endl << endl; #endif #if 0 //Old way of storing Camera Data (most of it was unnecessary) UNUSED cfliePitch = cflieCopter1->pitch(); cflieRoll = cflieCopter1->roll(); cflieYaw = cflieCopter1->yaw(); cflieThrust = cflieCopter1->thrust(); /* Legend for Camera Data Packet * Position * x t.pos[0] * y t.pos[1] * z t.pos[2] * * Orientation * yaw euler[0] Rotation * pitch euler[1] East-West movement * roll euler[2] North-South movement * Euler's range goes from -pi : +pi */ QUAD quad; quad.vrpnNow = 0; vrpn_data_t *vrpnData; vrpnData = (vrpn_data_t*) malloc(sizeof(vrpn_data_t)); vrpnData->usec = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnData->x = t.pos[0]; vrpnData->y = t.pos[1]; vrpnData->z = -t.pos[2] + 0.05; //Higher Altitude = Negative z //Added Offset for floor below camera system origin vrpnData->yaw = euler[0]; vrpnData->pitch = euler[1]; vrpnData->roll = euler[2]; quad.vrpnPrev = quad.vrpnNow; if (quad.vrpnNow == 0) { quad.vrpnPrev = 0; quad.vrpnTime0 = vrpnData->usec; quad.vrpnNow = vrpnData->usec; } else { quad.vrpnNow = vrpnData->usec - quad.vrpnTime0; } #endif //END UNUSED //==============YAW CORRECTION========================= (IMPORTANT!!!: YAW CONTROLLER INPUT IS INVERTED IN simple.cpp FILE***) camYawDeg1 = -(euler[0] * 57.2958); //Getting Camera Yaw (Converts From Radians TO Degrees) quadYaw1 = cflieCopter1->yaw(); //Getting Crazyflie Yaw if (frameCount == 50) { if (camYawDeg1 < 0.0) camYawDeg1Off = camYawDeg1 + 360.0; //Converts from +-180 to full 360 degree form else camYawDeg1Off = camYawDeg1; if(quadYaw1 < 0.0) quadYaw1Off = quadYaw1 + 360.0; else quadYaw1Off = quadYaw1; yawDifference1 = quadYaw1Off - camYawDeg1Off; cout << "Yaw1 Offset Taken: " << yawDifference1 << endl; } correctedYaw1 = camYawDeg1 + yawDifference1; if(correctedYaw1 > 180.0) correctedYaw1 -= 360.0; else if(correctedYaw1 < -180.0) correctedYaw1 += 360.0; //===============END YAW CORRECTION========================= #if USE_PRINTOUT cout << "X: " << t.pos[0] << endl; cout << "Y: " << t.pos[1] << endl; cout << "Z: " << -t.pos[2] + 0.05 << endl; // cout << "Quad Yaw: " << cflieCopter1->yaw() << endl; // cout << "Camera Yaw: " << camYawDeg1 << endl; // cout << "Yaw Offset: " << yawDifference1 << endl; // cout << "New Desired Yaw: " << yawDesired1 << endl; cout << "Frame Count: " << frameCount << endl; #endif #if USE_KEYBOARD if (cflieCopter1->m_enumFlightMode == LANDING_MODE) //Landing Mode { //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError1 = cos(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) - sin(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); // yError1 = sin(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) + cos(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, -0.4, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); takeOff1 = 0; } else if (cflieCopter1->m_enumFlightMode == MIRROR_MODE) { //Acts as Master xPositionDesired1 = -0.012; yPositionDesired1 = -0.200; zPositionDesired1 = 0.75; if( loopTime1Start - lastTime > 4.0 ) //Creates a 'Step' by changing setpoint every 4 seconds { toggle = !toggle; lastTime = loopTime1Start; } if(toggle) { xStepPositionError1 = xPositionDesired1 - xPosition1; yStepPositionError1 = yPositionDesired1 - yPosition1; controllerSetXYError(&pidCtrl1, xStepPositionError1, yStepPositionError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); } else //Shifts current x and y setpoint 0.65 meters { xStepPositionError1 = (xPositionDesired1 + 0.65) - xPosition1; yStepPositionError1 = (yPositionDesired1 + 0.65) - yPosition1; controllerSetXYError(&pidCtrl1, xStepPositionError1, yStepPositionError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1 + 0.65, yPositionDesired1 + 0.65, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); //cout << "Toggled!" << endl; } } else if (cflieCopter1->m_enumFlightMode == TAKEOFF_MODE) { //correctedYaw1 //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError1 = cos(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) - sin(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); // yError1 = sin(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) + cos(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); } else if (cflieCopter1->m_enumFlightMode == HAND_MODE) { //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError1 = cos(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) - sin(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); // yError1 = sin(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) + cos(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); xError1 = (xPositionHand - 0.5) - xPosition1; yError1 = (yPositionHand + 0.5) - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); } else if(flap){ //Flap Mode (OBSOLETE) // cflieCopter1->setThrust(20000); // cflieCopter2->setThrust(20000); //45000 Thrust of Crazyflie2.0 to match Crazyflie1.0 // cflieCopter2->setYaw(90); // lastTime = cflieCopter2->currentTime(); curTime = cflieCopter2->currentTime(); if( curTime - lastTime > 1.0 ) { toggle = !toggle; lastTime = curTime; } if( toggle ){ cflieCopter1->setThrust( 20000 ); printf("Low %.3lf ", curTime); } else { cflieCopter1->setThrust( 40000 ); printf("High %.3lf ", curTime); } } else if(cflieCopter1->m_enumFlightMode == GROUNDED_MODE){ controllerResetAllPID(&pidCtrl1); rollControlOutput1 = 0; pitchControlOutput1 = 0; yawControlOutput1 = 0; thrustControlOutput1 = 0; } else{ //Emergency Case (Should never happen) controllerResetAllPID(&pidCtrl1); rollControlOutput1 = 0; pitchControlOutput1 = 0; yawControlOutput1 = 0; thrustControlOutput1 = 0; } #else //If keyboard input NOT enabled then just run default Controller controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], -t.pos[2], correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); #endif RunCrazyflie(crRadio1, cflieCopter1, rollControlOutput1, pitchControlOutput1, yawControlOutput1, thrustControlOutput1); #if USE_LOGGING #if USE_BASIC_LOGGING fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); // fprintf(out1, "\n"); #else //FULL LOGGING ROUTINE (***CAUSES MAJOR BOTTLENECK IN CODE TIMING THE MORE VARIABLES YOU LOG***) fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t%.3f\t\t%.3f\t\t%.3f", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, pitchControlOutput1, rollControlOutput1, yawControlOutput1, thrustControlOutput1, cflieCopter1->radioRSSI(), euler[0], euler[1], euler[2], cflieCopter1->motor1(), cflieCopter1->motor2(), cflieCopter1->motor3(), cflieCopter1->motor4(), cflieCopter1->gyroX(), cflieCopter1->gyroY(), cflieCopter1->gyroZ()); // fprintf(out1, "\n"); #endif #endif #if 0 //(UNUSED) if (tcp_client_ON) { readMulticast(); //(argc < 1 = Listen Mode) // runTCPClient(); } #endif //cout << "PID Radio 2" << endl << endl; loopTime1End = cflieCopter1->currentTime() - initTime1; loopTime1 = loopTime1End - loopTime1Start; } else if(vrpnPacketBackup1 < 0){ //Failsafe so can't go below 0 (should never happen) | || (vrpnPacketBackup1 > 20)? vrpnPacketBackup1 = 0; } else if(vrpnPacketBackup1 >= 2){ vrpnPacketBackup1 --; // cout << "VRPN Packet Backup 1 Detected: " << vrpnPacketBackup1 << endl; }//End Packet Backup If check } //End Callback 1 </pre> </code> </blockquote> ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> d4dd58adeb0de4562492ffe7f2c558ce5f84ab0d File:TrackingToolsCrazyflieConstellationParams.png 6 45 147 2016-07-27T18:20:51Z Jnoronha 3 Camera System Software with Crazyflie and Hand Constellations and Server Port Info wikitext text/x-wiki Camera System Software with Crazyflie and Hand Constellations and Server Port Info 432e585d1f7446ecf7d98fcc6976aaeedbcd9b9e Callbacks 0 44 151 150 2016-07-27T19:31:02Z Jnoronha 3 /* Registering a Callback */ added flowchart for init function wikitext text/x-wiki A callback is a segment of code that will run only when a certain condition is satisfied. For the Swarm Platform, the callbacks we use are triggered by the VRPN communications protocol used by the Camera System. Whenever the Client receives a new packet of data from the Camera System the callback will be triggered. ==Registering a Callback== Before we can do anything we need to set up a callback that executes when new data is present. :1. Use the VRPN Library to create a ''Connection'' and ''Tracker_Remote'' object pointers (code in ''vrpn.cpp''): <blockquote> <code> <pre> vrpn_Connection *connection; vrpn_Tracker_Remote *trackerHand; vrpn_Tracker_Remote *tracker; vrpn_Tracker_Remote *tracker2; vrpn_Tracker_Remote *tracker3; vrpn_Tracker_Remote *tracker4; </pre> </code> </blockquote> ::'''Note:''' We need a ''Tracker_Remote'' object for each constellation we want to track (Hand and each Crazyflie in the Swarm) :2. Now we create a function to (code in ''vrpn.cpp''): :#Register the connection to the Server computer :#Assign each ''Tracker_Remote'' object to a valid constellation name on the Server computer :#Link that constellation to a callback :*Flowchart of the Init process [[Image:VRPN_INIT.png]] :*Full code <blockquote> <code> <pre> void vrpn_init(std::string connectionName, void (*callbackHand)(void*, const vrpn_TRACKERCB), void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback3)(void*, const vrpn_TRACKERCB), void (*callback4)(void*, const vrpn_TRACKERCB), char *key) { connection = vrpn_get_connection_by_name(connectionName.c_str()); #if USE_HAND trackerHand = new vrpn_Tracker_Remote("hand", connection); #endif tracker = new vrpn_Tracker_Remote("Crazyflie21", connection); tracker2 = new vrpn_Tracker_Remote("Crazyflie2", connection); tracker3 = new vrpn_Tracker_Remote("Crazyflie22", connection); tracker4 = new vrpn_Tracker_Remote("Crazyflie23", connection); #if USE_HAND trackerHand->register_change_handler(0, callbackHand); #endif tracker->register_change_handler(0, callback); tracker2->register_change_handler(0, callback2); tracker3->register_change_handler(0, callback3); tracker4->register_change_handler(0, callback4); usleep(2000); } </pre> </code> </blockquote> ::'''Note 1:''' We pass in the following as inputs to the function: ::*''string connectionName'' is the "'''IP address:Port'''" of the Computer running the Camera System ::**(You can see the ''VRPN Broadcast Port'' used in the on the middle-right pane called ''Streaming Properties'') ::*A callback pointer for each constellation we want to track (These will be established in the [[:Callbacks#Using a Callback in the Swarm Client|Using a Callback]] section) ::'''Note 2:''' Notice the names of each ''tracker'' '''match the names of the constellations''' in the Camera System Software (shown below): ::[[Image:TrackingToolsCrazyflieConstellationParams.png|800px]] ==Using a Callback in the Swarm Client== The Swarm Client needs to re-establish the connection to the VRPN server for each test. ===Initializing the Callbacks=== :1. Create the Callback Objects (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> void VRPN_CALLBACK handle_hand(void*, const vrpn_TRACKERCB t); void VRPN_CALLBACK handle_pos(void*, const vrpn_TRACKERCB t); //Old name scheme (represents Callback for Crazyflie1) void VRPN_CALLBACK handle_Crazyflie2(void*, const vrpn_TRACKERCB t); void VRPN_CALLBACK handle_Crazyflie3(void*, const vrpn_TRACKERCB t); void VRPN_CALLBACK handle_Crazyflie4(void*, const vrpn_TRACKERCB t); </pre> </code> </blockquote> :2. [[:Callbacks#Registering a Callback|Register the connection]] and constellations to the Callbacks (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> #if NUM_QUADS == 1 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, NULL, NULL, NULL, NULL); #elif NUM_QUADS == 2 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, handle_Crazyflie2, NULL, NULL, NULL); #elif NUM_QUADS == 3 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, handle_Crazyflie2, handle_Crazyflie3, NULL, NULL); #elif NUM_QUADS == 4 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, handle_Crazyflie2, handle_Crazyflie3, handle_Crazyflie4, NULL); #endif </pre> </code> </blockquote> ::'''Note:''' If we don't want to track a certain Crazyflie (i.e. we only want to fly 2 Crazyflies) we can just pass <code>NULL</code> into the init function for the callbacks we don't care about. ===Calling a Callback=== :3. Start the mainloop: <code>vrpn_go()</code> (code in ''vrpn.cpp'') (function called in ''eris_vrpn.cpp'') ::*A flowchart of the vrpn_go() function: [[Image:VRPNGO.png|500px]] ::*Full vrpn_go() code (code in ''vrpn.cpp''): <blockquote> <code> <pre> void vrpn_go() { int i = 0; //for ending the while loop while(!i){ readKeyboard(); //Triggers actions based on key value read nearGround(); #if USE_HAND updateHand(); //Checks for Valid Hand Gestures #endif //Calculates Total Loop Timing loopTimeTotalStart = cflieCopter1->currentTime() - initTime1; loopTimeTotalDelta = loopTimeTotalStart - loopTimeTotalPrev; loopTimeTotalPrev = loopTimeTotalStart; connection->mainloop(); //Pings the Server Connection to see if still alive #if USE_HAND trackerHand->mainloop(); //Checks if Hand constellation has new data (runs callback if true) #endif tracker->mainloop(); //IMPORTANT: Checks if Crazyflie1 constellation has new data (runs callback if true) tracker2->mainloop(); //Same... tracker3->mainloop(); tracker4->mainloop(); usleep(200); //Was 200 nonblock(1); usleep(1); i = kbhit(); //keyboard hit (state change) if (i!=0) { keystroke_now = fgetc(stdin); //Stores key value pressed if (keystroke_now == 'q') i=1; else{ i=0; } //fprintf(stderr,"%d ",i); } }//END WHILE if(keystroke_now == 'q'){ cout << "Program Forced End" << endl; } loopTimeTotalEnd = cflieCopter1->currentTime() - initTime1; loopTimeTotal = loopTimeTotalEnd - loopTimeTotalStart; } //END VRPN GO </pre> </code> </blockquote> ::'''Note:''' The most important part of this is the <code>tracker->mainloop();</code> functions. These functions are what calls the Callback if there is new data waiting!! ::You can see an example of the code that is executed whenever the [[:Callbacks#Full Callback Example|callback is triggered]] ==Full Callback Example== Below is a full Callback example for Crazyflie1: <blockquote> <code> <pre> #if NUM_QUADS >= 1 void VRPN_CALLBACK handle_pos(void*, const vrpn_TRACKERCB t) { //cout << "First Callback" << endl; if(vrpnPacketBackup1 < 2) //If VRPN Buffer does NOT have old packets stored up, run main code { loopTime1Start = cflieCopter1->currentTime() - initTime1; loopTime1Delta = loopTime1Start - loopTime1Prev; //Calculates time difference between each loop start loopTime1Prev = loopTime1Start; vrpnPacketTime1 = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnPacketDelta1 = vrpnPacketTime1 - vrpnPacketTime1Prev; //Calculates time between VRPN Data Packets (almost always 0.01 sec) vrpnPacketTime1Prev = vrpnPacketTime1; vrpnPacketBackup1 = ceil(loopTime1Delta/vrpnPacketDelta1); //Calculates estimated # of packets built up in VRPN buffer. controllerSetAllDt(&pidCtrl1, vrpnPacketDelta1); //Variable dt for controller based on time between packets | vrpnPacketDelta1 #if NUM_QUADS == 2 cflieCopter2->cheat_process_packets(); #elif NUM_QUADS == 3 cflieCopter3->cheat_process_packets(); #elif NUM_QUADS == 4 cflieCopter2->cheat_process_packets(); #endif crRadio1->clearPackets(); //Clears the USB Radio Buffer before switching Radio channels crRadio1->setChannel( cflieCopter1->radioChannel() ); frameCount++; // Get the euler angles q_vec_type euler; q_to_euler(euler, t.quat); xPosition1 = t.pos[0]; yPosition1 = t.pos[1]; //Stores X, Y, and Z Position for use in other Callbacks (external) zPosition1 = -t.pos[2] + 0.05; #if USE_PRINTOUT cout << "PID Radio 1" << endl << endl; #endif #if 0 //Old way of storing Camera Data (most of it was unnecessary) UNUSED cfliePitch = cflieCopter1->pitch(); cflieRoll = cflieCopter1->roll(); cflieYaw = cflieCopter1->yaw(); cflieThrust = cflieCopter1->thrust(); /* Legend for Camera Data Packet * Position * x t.pos[0] * y t.pos[1] * z t.pos[2] * * Orientation * yaw euler[0] Rotation * pitch euler[1] East-West movement * roll euler[2] North-South movement * Euler's range goes from -pi : +pi */ QUAD quad; quad.vrpnNow = 0; vrpn_data_t *vrpnData; vrpnData = (vrpn_data_t*) malloc(sizeof(vrpn_data_t)); vrpnData->usec = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnData->x = t.pos[0]; vrpnData->y = t.pos[1]; vrpnData->z = -t.pos[2] + 0.05; //Higher Altitude = Negative z //Added Offset for floor below camera system origin vrpnData->yaw = euler[0]; vrpnData->pitch = euler[1]; vrpnData->roll = euler[2]; quad.vrpnPrev = quad.vrpnNow; if (quad.vrpnNow == 0) { quad.vrpnPrev = 0; quad.vrpnTime0 = vrpnData->usec; quad.vrpnNow = vrpnData->usec; } else { quad.vrpnNow = vrpnData->usec - quad.vrpnTime0; } #endif //END UNUSED //==============YAW CORRECTION========================= (IMPORTANT!!!: YAW CONTROLLER INPUT IS INVERTED IN simple.cpp FILE***) camYawDeg1 = -(euler[0] * 57.2958); //Getting Camera Yaw (Converts From Radians TO Degrees) quadYaw1 = cflieCopter1->yaw(); //Getting Crazyflie Yaw if (frameCount == 50) { if (camYawDeg1 < 0.0) camYawDeg1Off = camYawDeg1 + 360.0; //Converts from +-180 to full 360 degree form else camYawDeg1Off = camYawDeg1; if(quadYaw1 < 0.0) quadYaw1Off = quadYaw1 + 360.0; else quadYaw1Off = quadYaw1; yawDifference1 = quadYaw1Off - camYawDeg1Off; cout << "Yaw1 Offset Taken: " << yawDifference1 << endl; } correctedYaw1 = camYawDeg1 + yawDifference1; if(correctedYaw1 > 180.0) correctedYaw1 -= 360.0; else if(correctedYaw1 < -180.0) correctedYaw1 += 360.0; //===============END YAW CORRECTION========================= #if USE_PRINTOUT cout << "X: " << t.pos[0] << endl; cout << "Y: " << t.pos[1] << endl; cout << "Z: " << -t.pos[2] + 0.05 << endl; // cout << "Quad Yaw: " << cflieCopter1->yaw() << endl; // cout << "Camera Yaw: " << camYawDeg1 << endl; // cout << "Yaw Offset: " << yawDifference1 << endl; // cout << "New Desired Yaw: " << yawDesired1 << endl; cout << "Frame Count: " << frameCount << endl; #endif #if USE_KEYBOARD if (cflieCopter1->m_enumFlightMode == LANDING_MODE) //Landing Mode { //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError1 = cos(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) - sin(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); // yError1 = sin(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) + cos(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, -0.4, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); takeOff1 = 0; } else if (cflieCopter1->m_enumFlightMode == MIRROR_MODE) { //Acts as Master xPositionDesired1 = -0.012; yPositionDesired1 = -0.200; zPositionDesired1 = 0.75; if( loopTime1Start - lastTime > 4.0 ) //Creates a 'Step' by changing setpoint every 4 seconds { toggle = !toggle; lastTime = loopTime1Start; } if(toggle) { xStepPositionError1 = xPositionDesired1 - xPosition1; yStepPositionError1 = yPositionDesired1 - yPosition1; controllerSetXYError(&pidCtrl1, xStepPositionError1, yStepPositionError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); } else //Shifts current x and y setpoint 0.65 meters { xStepPositionError1 = (xPositionDesired1 + 0.65) - xPosition1; yStepPositionError1 = (yPositionDesired1 + 0.65) - yPosition1; controllerSetXYError(&pidCtrl1, xStepPositionError1, yStepPositionError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1 + 0.65, yPositionDesired1 + 0.65, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); //cout << "Toggled!" << endl; } } else if (cflieCopter1->m_enumFlightMode == TAKEOFF_MODE) { //correctedYaw1 //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError1 = cos(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) - sin(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); // yError1 = sin(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) + cos(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); } else if (cflieCopter1->m_enumFlightMode == HAND_MODE) { //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError1 = cos(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) - sin(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); // yError1 = sin(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) + cos(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); xError1 = (xPositionHand - 0.5) - xPosition1; yError1 = (yPositionHand + 0.5) - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); } else if(flap){ //Flap Mode (OBSOLETE) // cflieCopter1->setThrust(20000); // cflieCopter2->setThrust(20000); //45000 Thrust of Crazyflie2.0 to match Crazyflie1.0 // cflieCopter2->setYaw(90); // lastTime = cflieCopter2->currentTime(); curTime = cflieCopter2->currentTime(); if( curTime - lastTime > 1.0 ) { toggle = !toggle; lastTime = curTime; } if( toggle ){ cflieCopter1->setThrust( 20000 ); printf("Low %.3lf ", curTime); } else { cflieCopter1->setThrust( 40000 ); printf("High %.3lf ", curTime); } } else if(cflieCopter1->m_enumFlightMode == GROUNDED_MODE){ controllerResetAllPID(&pidCtrl1); rollControlOutput1 = 0; pitchControlOutput1 = 0; yawControlOutput1 = 0; thrustControlOutput1 = 0; } else{ //Emergency Case (Should never happen) controllerResetAllPID(&pidCtrl1); rollControlOutput1 = 0; pitchControlOutput1 = 0; yawControlOutput1 = 0; thrustControlOutput1 = 0; } #else //If keyboard input NOT enabled then just run default Controller controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], -t.pos[2], correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); #endif RunCrazyflie(crRadio1, cflieCopter1, rollControlOutput1, pitchControlOutput1, yawControlOutput1, thrustControlOutput1); #if USE_LOGGING #if USE_BASIC_LOGGING fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); // fprintf(out1, "\n"); #else //FULL LOGGING ROUTINE (***CAUSES MAJOR BOTTLENECK IN CODE TIMING THE MORE VARIABLES YOU LOG***) fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t%.3f\t\t%.3f\t\t%.3f", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, pitchControlOutput1, rollControlOutput1, yawControlOutput1, thrustControlOutput1, cflieCopter1->radioRSSI(), euler[0], euler[1], euler[2], cflieCopter1->motor1(), cflieCopter1->motor2(), cflieCopter1->motor3(), cflieCopter1->motor4(), cflieCopter1->gyroX(), cflieCopter1->gyroY(), cflieCopter1->gyroZ()); // fprintf(out1, "\n"); #endif #endif #if 0 //(UNUSED) if (tcp_client_ON) { readMulticast(); //(argc < 1 = Listen Mode) // runTCPClient(); } #endif //cout << "PID Radio 2" << endl << endl; loopTime1End = cflieCopter1->currentTime() - initTime1; loopTime1 = loopTime1End - loopTime1Start; } else if(vrpnPacketBackup1 < 0){ //Failsafe so can't go below 0 (should never happen) | || (vrpnPacketBackup1 > 20)? vrpnPacketBackup1 = 0; } else if(vrpnPacketBackup1 >= 2){ vrpnPacketBackup1 --; // cout << "VRPN Packet Backup 1 Detected: " << vrpnPacketBackup1 << endl; }//End Packet Backup If check } //End Callback 1 </pre> </code> </blockquote> ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> e5d7948494835bae2de18d105e8c32e9281a7137 152 151 2016-07-27T19:37:24Z Jnoronha 3 added link to vrpn and camera system section wikitext text/x-wiki A callback is a segment of code that will run only when a certain condition is satisfied. For the Swarm Platform, the callbacks we use are triggered by the VRPN communications protocol used by the Camera System. Whenever the Client receives a new packet of data from the Camera System the callback will be triggered. See [[Camera System and VRPN|VRPN and the Camera System]] if you want more detail on those systems before you start. ==Registering a Callback== Before we can do anything we need to set up a callback that executes when new data is present. :1. Use the VRPN Library to create a ''Connection'' and ''Tracker_Remote'' object pointers (code in ''vrpn.cpp''): <blockquote> <code> <pre> vrpn_Connection *connection; vrpn_Tracker_Remote *trackerHand; vrpn_Tracker_Remote *tracker; vrpn_Tracker_Remote *tracker2; vrpn_Tracker_Remote *tracker3; vrpn_Tracker_Remote *tracker4; </pre> </code> </blockquote> ::'''Note:''' We need a ''Tracker_Remote'' object for each constellation we want to track (Hand and each Crazyflie in the Swarm) :2. Now we create a function to (code in ''vrpn.cpp''): :#Register the connection to the Server computer :#Assign each ''Tracker_Remote'' object to a valid constellation name on the Server computer :#Link that constellation to a callback :*Flowchart of the Init process [[Image:VRPN_INIT.png]] :*Full code <blockquote> <code> <pre> void vrpn_init(std::string connectionName, void (*callbackHand)(void*, const vrpn_TRACKERCB), void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback3)(void*, const vrpn_TRACKERCB), void (*callback4)(void*, const vrpn_TRACKERCB), char *key) { connection = vrpn_get_connection_by_name(connectionName.c_str()); #if USE_HAND trackerHand = new vrpn_Tracker_Remote("hand", connection); #endif tracker = new vrpn_Tracker_Remote("Crazyflie21", connection); tracker2 = new vrpn_Tracker_Remote("Crazyflie2", connection); tracker3 = new vrpn_Tracker_Remote("Crazyflie22", connection); tracker4 = new vrpn_Tracker_Remote("Crazyflie23", connection); #if USE_HAND trackerHand->register_change_handler(0, callbackHand); #endif tracker->register_change_handler(0, callback); tracker2->register_change_handler(0, callback2); tracker3->register_change_handler(0, callback3); tracker4->register_change_handler(0, callback4); usleep(2000); } </pre> </code> </blockquote> ::'''Note 1:''' We pass in the following as inputs to the function: ::*''string connectionName'' is the "'''IP address:Port'''" of the Computer running the Camera System ::**(You can see the ''VRPN Broadcast Port'' used in the on the middle-right pane called ''Streaming Properties'') ::*A callback pointer for each constellation we want to track (These will be established in the [[:Callbacks#Using a Callback in the Swarm Client|Using a Callback]] section) ::'''Note 2:''' Notice the names of each ''tracker'' '''match the names of the constellations''' in the Camera System Software (shown below): ::[[Image:TrackingToolsCrazyflieConstellationParams.png|800px]] ==Using a Callback in the Swarm Client== The Swarm Client needs to re-establish the connection to the VRPN server for each test. ===Initializing the Callbacks=== :1. Create the Callback Objects (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> void VRPN_CALLBACK handle_hand(void*, const vrpn_TRACKERCB t); void VRPN_CALLBACK handle_pos(void*, const vrpn_TRACKERCB t); //Old name scheme (represents Callback for Crazyflie1) void VRPN_CALLBACK handle_Crazyflie2(void*, const vrpn_TRACKERCB t); void VRPN_CALLBACK handle_Crazyflie3(void*, const vrpn_TRACKERCB t); void VRPN_CALLBACK handle_Crazyflie4(void*, const vrpn_TRACKERCB t); </pre> </code> </blockquote> :2. [[:Callbacks#Registering a Callback|Register the connection]] and constellations to the Callbacks (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> #if NUM_QUADS == 1 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, NULL, NULL, NULL, NULL); #elif NUM_QUADS == 2 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, handle_Crazyflie2, NULL, NULL, NULL); #elif NUM_QUADS == 3 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, handle_Crazyflie2, handle_Crazyflie3, NULL, NULL); #elif NUM_QUADS == 4 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, handle_Crazyflie2, handle_Crazyflie3, handle_Crazyflie4, NULL); #endif </pre> </code> </blockquote> ::'''Note:''' If we don't want to track a certain Crazyflie (i.e. we only want to fly 2 Crazyflies) we can just pass <code>NULL</code> into the init function for the callbacks we don't care about. ===Calling a Callback=== :3. Start the mainloop: <code>vrpn_go()</code> (code in ''vrpn.cpp'') (function called in ''eris_vrpn.cpp'') ::*A flowchart of the vrpn_go() function: [[Image:VRPNGO.png|500px]] ::*Full vrpn_go() code (code in ''vrpn.cpp''): <blockquote> <code> <pre> void vrpn_go() { int i = 0; //for ending the while loop while(!i){ readKeyboard(); //Triggers actions based on key value read nearGround(); #if USE_HAND updateHand(); //Checks for Valid Hand Gestures #endif //Calculates Total Loop Timing loopTimeTotalStart = cflieCopter1->currentTime() - initTime1; loopTimeTotalDelta = loopTimeTotalStart - loopTimeTotalPrev; loopTimeTotalPrev = loopTimeTotalStart; connection->mainloop(); //Pings the Server Connection to see if still alive #if USE_HAND trackerHand->mainloop(); //Checks if Hand constellation has new data (runs callback if true) #endif tracker->mainloop(); //IMPORTANT: Checks if Crazyflie1 constellation has new data (runs callback if true) tracker2->mainloop(); //Same... tracker3->mainloop(); tracker4->mainloop(); usleep(200); //Was 200 nonblock(1); usleep(1); i = kbhit(); //keyboard hit (state change) if (i!=0) { keystroke_now = fgetc(stdin); //Stores key value pressed if (keystroke_now == 'q') i=1; else{ i=0; } //fprintf(stderr,"%d ",i); } }//END WHILE if(keystroke_now == 'q'){ cout << "Program Forced End" << endl; } loopTimeTotalEnd = cflieCopter1->currentTime() - initTime1; loopTimeTotal = loopTimeTotalEnd - loopTimeTotalStart; } //END VRPN GO </pre> </code> </blockquote> ::'''Note:''' The most important part of this is the <code>tracker->mainloop();</code> functions. These functions are what calls the Callback if there is new data waiting!! ::You can see an example of the code that is executed whenever the [[:Callbacks#Full Callback Example|callback is triggered]] ==Full Callback Example== Below is a full Callback example for Crazyflie1: <blockquote> <code> <pre> #if NUM_QUADS >= 1 void VRPN_CALLBACK handle_pos(void*, const vrpn_TRACKERCB t) { //cout << "First Callback" << endl; if(vrpnPacketBackup1 < 2) //If VRPN Buffer does NOT have old packets stored up, run main code { loopTime1Start = cflieCopter1->currentTime() - initTime1; loopTime1Delta = loopTime1Start - loopTime1Prev; //Calculates time difference between each loop start loopTime1Prev = loopTime1Start; vrpnPacketTime1 = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnPacketDelta1 = vrpnPacketTime1 - vrpnPacketTime1Prev; //Calculates time between VRPN Data Packets (almost always 0.01 sec) vrpnPacketTime1Prev = vrpnPacketTime1; vrpnPacketBackup1 = ceil(loopTime1Delta/vrpnPacketDelta1); //Calculates estimated # of packets built up in VRPN buffer. controllerSetAllDt(&pidCtrl1, vrpnPacketDelta1); //Variable dt for controller based on time between packets | vrpnPacketDelta1 #if NUM_QUADS == 2 cflieCopter2->cheat_process_packets(); #elif NUM_QUADS == 3 cflieCopter3->cheat_process_packets(); #elif NUM_QUADS == 4 cflieCopter2->cheat_process_packets(); #endif crRadio1->clearPackets(); //Clears the USB Radio Buffer before switching Radio channels crRadio1->setChannel( cflieCopter1->radioChannel() ); frameCount++; // Get the euler angles q_vec_type euler; q_to_euler(euler, t.quat); xPosition1 = t.pos[0]; yPosition1 = t.pos[1]; //Stores X, Y, and Z Position for use in other Callbacks (external) zPosition1 = -t.pos[2] + 0.05; #if USE_PRINTOUT cout << "PID Radio 1" << endl << endl; #endif #if 0 //Old way of storing Camera Data (most of it was unnecessary) UNUSED cfliePitch = cflieCopter1->pitch(); cflieRoll = cflieCopter1->roll(); cflieYaw = cflieCopter1->yaw(); cflieThrust = cflieCopter1->thrust(); /* Legend for Camera Data Packet * Position * x t.pos[0] * y t.pos[1] * z t.pos[2] * * Orientation * yaw euler[0] Rotation * pitch euler[1] East-West movement * roll euler[2] North-South movement * Euler's range goes from -pi : +pi */ QUAD quad; quad.vrpnNow = 0; vrpn_data_t *vrpnData; vrpnData = (vrpn_data_t*) malloc(sizeof(vrpn_data_t)); vrpnData->usec = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnData->x = t.pos[0]; vrpnData->y = t.pos[1]; vrpnData->z = -t.pos[2] + 0.05; //Higher Altitude = Negative z //Added Offset for floor below camera system origin vrpnData->yaw = euler[0]; vrpnData->pitch = euler[1]; vrpnData->roll = euler[2]; quad.vrpnPrev = quad.vrpnNow; if (quad.vrpnNow == 0) { quad.vrpnPrev = 0; quad.vrpnTime0 = vrpnData->usec; quad.vrpnNow = vrpnData->usec; } else { quad.vrpnNow = vrpnData->usec - quad.vrpnTime0; } #endif //END UNUSED //==============YAW CORRECTION========================= (IMPORTANT!!!: YAW CONTROLLER INPUT IS INVERTED IN simple.cpp FILE***) camYawDeg1 = -(euler[0] * 57.2958); //Getting Camera Yaw (Converts From Radians TO Degrees) quadYaw1 = cflieCopter1->yaw(); //Getting Crazyflie Yaw if (frameCount == 50) { if (camYawDeg1 < 0.0) camYawDeg1Off = camYawDeg1 + 360.0; //Converts from +-180 to full 360 degree form else camYawDeg1Off = camYawDeg1; if(quadYaw1 < 0.0) quadYaw1Off = quadYaw1 + 360.0; else quadYaw1Off = quadYaw1; yawDifference1 = quadYaw1Off - camYawDeg1Off; cout << "Yaw1 Offset Taken: " << yawDifference1 << endl; } correctedYaw1 = camYawDeg1 + yawDifference1; if(correctedYaw1 > 180.0) correctedYaw1 -= 360.0; else if(correctedYaw1 < -180.0) correctedYaw1 += 360.0; //===============END YAW CORRECTION========================= #if USE_PRINTOUT cout << "X: " << t.pos[0] << endl; cout << "Y: " << t.pos[1] << endl; cout << "Z: " << -t.pos[2] + 0.05 << endl; // cout << "Quad Yaw: " << cflieCopter1->yaw() << endl; // cout << "Camera Yaw: " << camYawDeg1 << endl; // cout << "Yaw Offset: " << yawDifference1 << endl; // cout << "New Desired Yaw: " << yawDesired1 << endl; cout << "Frame Count: " << frameCount << endl; #endif #if USE_KEYBOARD if (cflieCopter1->m_enumFlightMode == LANDING_MODE) //Landing Mode { //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError1 = cos(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) - sin(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); // yError1 = sin(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) + cos(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, -0.4, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); takeOff1 = 0; } else if (cflieCopter1->m_enumFlightMode == MIRROR_MODE) { //Acts as Master xPositionDesired1 = -0.012; yPositionDesired1 = -0.200; zPositionDesired1 = 0.75; if( loopTime1Start - lastTime > 4.0 ) //Creates a 'Step' by changing setpoint every 4 seconds { toggle = !toggle; lastTime = loopTime1Start; } if(toggle) { xStepPositionError1 = xPositionDesired1 - xPosition1; yStepPositionError1 = yPositionDesired1 - yPosition1; controllerSetXYError(&pidCtrl1, xStepPositionError1, yStepPositionError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); } else //Shifts current x and y setpoint 0.65 meters { xStepPositionError1 = (xPositionDesired1 + 0.65) - xPosition1; yStepPositionError1 = (yPositionDesired1 + 0.65) - yPosition1; controllerSetXYError(&pidCtrl1, xStepPositionError1, yStepPositionError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1 + 0.65, yPositionDesired1 + 0.65, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); //cout << "Toggled!" << endl; } } else if (cflieCopter1->m_enumFlightMode == TAKEOFF_MODE) { //correctedYaw1 //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError1 = cos(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) - sin(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); // yError1 = sin(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) + cos(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); } else if (cflieCopter1->m_enumFlightMode == HAND_MODE) { //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError1 = cos(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) - sin(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); // yError1 = sin(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) + cos(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); xError1 = (xPositionHand - 0.5) - xPosition1; yError1 = (yPositionHand + 0.5) - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); } else if(flap){ //Flap Mode (OBSOLETE) // cflieCopter1->setThrust(20000); // cflieCopter2->setThrust(20000); //45000 Thrust of Crazyflie2.0 to match Crazyflie1.0 // cflieCopter2->setYaw(90); // lastTime = cflieCopter2->currentTime(); curTime = cflieCopter2->currentTime(); if( curTime - lastTime > 1.0 ) { toggle = !toggle; lastTime = curTime; } if( toggle ){ cflieCopter1->setThrust( 20000 ); printf("Low %.3lf ", curTime); } else { cflieCopter1->setThrust( 40000 ); printf("High %.3lf ", curTime); } } else if(cflieCopter1->m_enumFlightMode == GROUNDED_MODE){ controllerResetAllPID(&pidCtrl1); rollControlOutput1 = 0; pitchControlOutput1 = 0; yawControlOutput1 = 0; thrustControlOutput1 = 0; } else{ //Emergency Case (Should never happen) controllerResetAllPID(&pidCtrl1); rollControlOutput1 = 0; pitchControlOutput1 = 0; yawControlOutput1 = 0; thrustControlOutput1 = 0; } #else //If keyboard input NOT enabled then just run default Controller controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], -t.pos[2], correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); #endif RunCrazyflie(crRadio1, cflieCopter1, rollControlOutput1, pitchControlOutput1, yawControlOutput1, thrustControlOutput1); #if USE_LOGGING #if USE_BASIC_LOGGING fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); // fprintf(out1, "\n"); #else //FULL LOGGING ROUTINE (***CAUSES MAJOR BOTTLENECK IN CODE TIMING THE MORE VARIABLES YOU LOG***) fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t%.3f\t\t%.3f\t\t%.3f", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, pitchControlOutput1, rollControlOutput1, yawControlOutput1, thrustControlOutput1, cflieCopter1->radioRSSI(), euler[0], euler[1], euler[2], cflieCopter1->motor1(), cflieCopter1->motor2(), cflieCopter1->motor3(), cflieCopter1->motor4(), cflieCopter1->gyroX(), cflieCopter1->gyroY(), cflieCopter1->gyroZ()); // fprintf(out1, "\n"); #endif #endif #if 0 //(UNUSED) if (tcp_client_ON) { readMulticast(); //(argc < 1 = Listen Mode) // runTCPClient(); } #endif //cout << "PID Radio 2" << endl << endl; loopTime1End = cflieCopter1->currentTime() - initTime1; loopTime1 = loopTime1End - loopTime1Start; } else if(vrpnPacketBackup1 < 0){ //Failsafe so can't go below 0 (should never happen) | || (vrpnPacketBackup1 > 20)? vrpnPacketBackup1 = 0; } else if(vrpnPacketBackup1 >= 2){ vrpnPacketBackup1 --; // cout << "VRPN Packet Backup 1 Detected: " << vrpnPacketBackup1 << endl; }//End Packet Backup If check } //End Callback 1 </pre> </code> </blockquote> ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> e54328f5645cdae2c8e508ea41a94a2d96249159 153 152 2016-07-28T17:16:43Z Jnoronha 3 /* Full Callback Example */ added timestamp to callback example wikitext text/x-wiki A callback is a segment of code that will run only when a certain condition is satisfied. For the Swarm Platform, the callbacks we use are triggered by the VRPN communications protocol used by the Camera System. Whenever the Client receives a new packet of data from the Camera System the callback will be triggered. See [[Camera System and VRPN|VRPN and the Camera System]] if you want more detail on those systems before you start. ==Registering a Callback== Before we can do anything we need to set up a callback that executes when new data is present. :1. Use the VRPN Library to create a ''Connection'' and ''Tracker_Remote'' object pointers (code in ''vrpn.cpp''): <blockquote> <code> <pre> vrpn_Connection *connection; vrpn_Tracker_Remote *trackerHand; vrpn_Tracker_Remote *tracker; vrpn_Tracker_Remote *tracker2; vrpn_Tracker_Remote *tracker3; vrpn_Tracker_Remote *tracker4; </pre> </code> </blockquote> ::'''Note:''' We need a ''Tracker_Remote'' object for each constellation we want to track (Hand and each Crazyflie in the Swarm) :2. Now we create a function to (code in ''vrpn.cpp''): :#Register the connection to the Server computer :#Assign each ''Tracker_Remote'' object to a valid constellation name on the Server computer :#Link that constellation to a callback :*Flowchart of the Init process [[Image:VRPN_INIT.png]] :*Full code <blockquote> <code> <pre> void vrpn_init(std::string connectionName, void (*callbackHand)(void*, const vrpn_TRACKERCB), void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback3)(void*, const vrpn_TRACKERCB), void (*callback4)(void*, const vrpn_TRACKERCB), char *key) { connection = vrpn_get_connection_by_name(connectionName.c_str()); #if USE_HAND trackerHand = new vrpn_Tracker_Remote("hand", connection); #endif tracker = new vrpn_Tracker_Remote("Crazyflie21", connection); tracker2 = new vrpn_Tracker_Remote("Crazyflie2", connection); tracker3 = new vrpn_Tracker_Remote("Crazyflie22", connection); tracker4 = new vrpn_Tracker_Remote("Crazyflie23", connection); #if USE_HAND trackerHand->register_change_handler(0, callbackHand); #endif tracker->register_change_handler(0, callback); tracker2->register_change_handler(0, callback2); tracker3->register_change_handler(0, callback3); tracker4->register_change_handler(0, callback4); usleep(2000); } </pre> </code> </blockquote> ::'''Note 1:''' We pass in the following as inputs to the function: ::*''string connectionName'' is the "'''IP address:Port'''" of the Computer running the Camera System ::**(You can see the ''VRPN Broadcast Port'' used in the on the middle-right pane called ''Streaming Properties'') ::*A callback pointer for each constellation we want to track (These will be established in the [[:Callbacks#Using a Callback in the Swarm Client|Using a Callback]] section) ::'''Note 2:''' Notice the names of each ''tracker'' '''match the names of the constellations''' in the Camera System Software (shown below): ::[[Image:TrackingToolsCrazyflieConstellationParams.png|800px]] ==Using a Callback in the Swarm Client== The Swarm Client needs to re-establish the connection to the VRPN server for each test. ===Initializing the Callbacks=== :1. Create the Callback Objects (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> void VRPN_CALLBACK handle_hand(void*, const vrpn_TRACKERCB t); void VRPN_CALLBACK handle_pos(void*, const vrpn_TRACKERCB t); //Old name scheme (represents Callback for Crazyflie1) void VRPN_CALLBACK handle_Crazyflie2(void*, const vrpn_TRACKERCB t); void VRPN_CALLBACK handle_Crazyflie3(void*, const vrpn_TRACKERCB t); void VRPN_CALLBACK handle_Crazyflie4(void*, const vrpn_TRACKERCB t); </pre> </code> </blockquote> :2. [[:Callbacks#Registering a Callback|Register the connection]] and constellations to the Callbacks (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> #if NUM_QUADS == 1 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, NULL, NULL, NULL, NULL); #elif NUM_QUADS == 2 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, handle_Crazyflie2, NULL, NULL, NULL); #elif NUM_QUADS == 3 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, handle_Crazyflie2, handle_Crazyflie3, NULL, NULL); #elif NUM_QUADS == 4 vrpn_init("192.168.0.120:3883", handle_hand, handle_pos, handle_Crazyflie2, handle_Crazyflie3, handle_Crazyflie4, NULL); #endif </pre> </code> </blockquote> ::'''Note:''' If we don't want to track a certain Crazyflie (i.e. we only want to fly 2 Crazyflies) we can just pass <code>NULL</code> into the init function for the callbacks we don't care about. ===Calling a Callback=== :3. Start the mainloop: <code>vrpn_go()</code> (code in ''vrpn.cpp'') (function called in ''eris_vrpn.cpp'') ::*A flowchart of the vrpn_go() function: [[Image:VRPNGO.png|500px]] ::*Full vrpn_go() code (code in ''vrpn.cpp''): <blockquote> <code> <pre> void vrpn_go() { int i = 0; //for ending the while loop while(!i){ readKeyboard(); //Triggers actions based on key value read nearGround(); #if USE_HAND updateHand(); //Checks for Valid Hand Gestures #endif //Calculates Total Loop Timing loopTimeTotalStart = cflieCopter1->currentTime() - initTime1; loopTimeTotalDelta = loopTimeTotalStart - loopTimeTotalPrev; loopTimeTotalPrev = loopTimeTotalStart; connection->mainloop(); //Pings the Server Connection to see if still alive #if USE_HAND trackerHand->mainloop(); //Checks if Hand constellation has new data (runs callback if true) #endif tracker->mainloop(); //IMPORTANT: Checks if Crazyflie1 constellation has new data (runs callback if true) tracker2->mainloop(); //Same... tracker3->mainloop(); tracker4->mainloop(); usleep(200); //Was 200 nonblock(1); usleep(1); i = kbhit(); //keyboard hit (state change) if (i!=0) { keystroke_now = fgetc(stdin); //Stores key value pressed if (keystroke_now == 'q') i=1; else{ i=0; } //fprintf(stderr,"%d ",i); } }//END WHILE if(keystroke_now == 'q'){ cout << "Program Forced End" << endl; } loopTimeTotalEnd = cflieCopter1->currentTime() - initTime1; loopTimeTotal = loopTimeTotalEnd - loopTimeTotalStart; } //END VRPN GO </pre> </code> </blockquote> ::'''Note:''' The most important part of this is the <code>tracker->mainloop();</code> functions. These functions are what calls the Callback if there is new data waiting!! ::You can see an example of the code that is executed whenever the [[:Callbacks#Full Callback Example|callback is triggered]] ==Full Callback Example== Below is a full Callback example for Crazyflie1 (as of 7/27/16): <blockquote> <code> <pre> #if NUM_QUADS >= 1 void VRPN_CALLBACK handle_pos(void*, const vrpn_TRACKERCB t) { //cout << "First Callback" << endl; if(vrpnPacketBackup1 < 2) //If VRPN Buffer does NOT have old packets stored up, run main code { loopTime1Start = cflieCopter1->currentTime() - initTime1; loopTime1Delta = loopTime1Start - loopTime1Prev; //Calculates time difference between each loop start loopTime1Prev = loopTime1Start; vrpnPacketTime1 = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnPacketDelta1 = vrpnPacketTime1 - vrpnPacketTime1Prev; //Calculates time between VRPN Data Packets (almost always 0.01 sec) vrpnPacketTime1Prev = vrpnPacketTime1; vrpnPacketBackup1 = ceil(loopTime1Delta/vrpnPacketDelta1); //Calculates estimated # of packets built up in VRPN buffer. controllerSetAllDt(&pidCtrl1, vrpnPacketDelta1); //Variable dt for controller based on time between packets | vrpnPacketDelta1 #if NUM_QUADS == 2 cflieCopter2->cheat_process_packets(); #elif NUM_QUADS == 3 cflieCopter3->cheat_process_packets(); #elif NUM_QUADS == 4 cflieCopter2->cheat_process_packets(); #endif crRadio1->clearPackets(); //Clears the USB Radio Buffer before switching Radio channels crRadio1->setChannel( cflieCopter1->radioChannel() ); frameCount++; // Get the euler angles q_vec_type euler; q_to_euler(euler, t.quat); xPosition1 = t.pos[0]; yPosition1 = t.pos[1]; //Stores X, Y, and Z Position for use in other Callbacks (external) zPosition1 = -t.pos[2] + 0.05; #if USE_PRINTOUT cout << "PID Radio 1" << endl << endl; #endif #if 0 //Old way of storing Camera Data (most of it was unnecessary) UNUSED cfliePitch = cflieCopter1->pitch(); cflieRoll = cflieCopter1->roll(); cflieYaw = cflieCopter1->yaw(); cflieThrust = cflieCopter1->thrust(); /* Legend for Camera Data Packet * Position * x t.pos[0] * y t.pos[1] * z t.pos[2] * * Orientation * yaw euler[0] Rotation * pitch euler[1] East-West movement * roll euler[2] North-South movement * Euler's range goes from -pi : +pi */ QUAD quad; quad.vrpnNow = 0; vrpn_data_t *vrpnData; vrpnData = (vrpn_data_t*) malloc(sizeof(vrpn_data_t)); vrpnData->usec = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnData->x = t.pos[0]; vrpnData->y = t.pos[1]; vrpnData->z = -t.pos[2] + 0.05; //Higher Altitude = Negative z //Added Offset for floor below camera system origin vrpnData->yaw = euler[0]; vrpnData->pitch = euler[1]; vrpnData->roll = euler[2]; quad.vrpnPrev = quad.vrpnNow; if (quad.vrpnNow == 0) { quad.vrpnPrev = 0; quad.vrpnTime0 = vrpnData->usec; quad.vrpnNow = vrpnData->usec; } else { quad.vrpnNow = vrpnData->usec - quad.vrpnTime0; } #endif //END UNUSED //==============YAW CORRECTION========================= (IMPORTANT!!!: YAW CONTROLLER INPUT IS INVERTED IN simple.cpp FILE***) camYawDeg1 = -(euler[0] * 57.2958); //Getting Camera Yaw (Converts From Radians TO Degrees) quadYaw1 = cflieCopter1->yaw(); //Getting Crazyflie Yaw if (frameCount == 50) { if (camYawDeg1 < 0.0) camYawDeg1Off = camYawDeg1 + 360.0; //Converts from +-180 to full 360 degree form else camYawDeg1Off = camYawDeg1; if(quadYaw1 < 0.0) quadYaw1Off = quadYaw1 + 360.0; else quadYaw1Off = quadYaw1; yawDifference1 = quadYaw1Off - camYawDeg1Off; cout << "Yaw1 Offset Taken: " << yawDifference1 << endl; } correctedYaw1 = camYawDeg1 + yawDifference1; if(correctedYaw1 > 180.0) correctedYaw1 -= 360.0; else if(correctedYaw1 < -180.0) correctedYaw1 += 360.0; //===============END YAW CORRECTION========================= #if USE_PRINTOUT cout << "X: " << t.pos[0] << endl; cout << "Y: " << t.pos[1] << endl; cout << "Z: " << -t.pos[2] + 0.05 << endl; // cout << "Quad Yaw: " << cflieCopter1->yaw() << endl; // cout << "Camera Yaw: " << camYawDeg1 << endl; // cout << "Yaw Offset: " << yawDifference1 << endl; // cout << "New Desired Yaw: " << yawDesired1 << endl; cout << "Frame Count: " << frameCount << endl; #endif #if USE_KEYBOARD if (cflieCopter1->m_enumFlightMode == LANDING_MODE) //Landing Mode { //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError1 = cos(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) - sin(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); // yError1 = sin(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) + cos(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, -0.4, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); takeOff1 = 0; } else if (cflieCopter1->m_enumFlightMode == MIRROR_MODE) { //Acts as Master xPositionDesired1 = -0.012; yPositionDesired1 = -0.200; zPositionDesired1 = 0.75; if( loopTime1Start - lastTime > 4.0 ) //Creates a 'Step' by changing setpoint every 4 seconds { toggle = !toggle; lastTime = loopTime1Start; } if(toggle) { xStepPositionError1 = xPositionDesired1 - xPosition1; yStepPositionError1 = yPositionDesired1 - yPosition1; controllerSetXYError(&pidCtrl1, xStepPositionError1, yStepPositionError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); } else //Shifts current x and y setpoint 0.65 meters { xStepPositionError1 = (xPositionDesired1 + 0.65) - xPosition1; yStepPositionError1 = (yPositionDesired1 + 0.65) - yPosition1; controllerSetXYError(&pidCtrl1, xStepPositionError1, yStepPositionError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1 + 0.65, yPositionDesired1 + 0.65, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); //cout << "Toggled!" << endl; } } else if (cflieCopter1->m_enumFlightMode == TAKEOFF_MODE) { //correctedYaw1 //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError1 = cos(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) - sin(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); // yError1 = sin(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) + cos(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); } else if (cflieCopter1->m_enumFlightMode == HAND_MODE) { //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError1 = cos(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) - sin(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); // yError1 = sin(correctedYaw1 / 57.2958)*(xPositionDesired1 - xPosition1) + cos(correctedYaw1 / 57.2958)*(yPositionDesired1 - yPosition1); xError1 = (xPositionHand - 0.5) - xPosition1; yError1 = (yPositionHand + 0.5) - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); } else if(flap){ //Flap Mode (OBSOLETE) // cflieCopter1->setThrust(20000); // cflieCopter2->setThrust(20000); //45000 Thrust of Crazyflie2.0 to match Crazyflie1.0 // cflieCopter2->setYaw(90); // lastTime = cflieCopter2->currentTime(); curTime = cflieCopter2->currentTime(); if( curTime - lastTime > 1.0 ) { toggle = !toggle; lastTime = curTime; } if( toggle ){ cflieCopter1->setThrust( 20000 ); printf("Low %.3lf ", curTime); } else { cflieCopter1->setThrust( 40000 ); printf("High %.3lf ", curTime); } } else if(cflieCopter1->m_enumFlightMode == GROUNDED_MODE){ controllerResetAllPID(&pidCtrl1); rollControlOutput1 = 0; pitchControlOutput1 = 0; yawControlOutput1 = 0; thrustControlOutput1 = 0; } else{ //Emergency Case (Should never happen) controllerResetAllPID(&pidCtrl1); rollControlOutput1 = 0; pitchControlOutput1 = 0; yawControlOutput1 = 0; thrustControlOutput1 = 0; } #else //If keyboard input NOT enabled then just run default Controller controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], -t.pos[2], correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); #endif RunCrazyflie(crRadio1, cflieCopter1, rollControlOutput1, pitchControlOutput1, yawControlOutput1, thrustControlOutput1); #if USE_LOGGING #if USE_BASIC_LOGGING fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); // fprintf(out1, "\n"); #else //FULL LOGGING ROUTINE (***CAUSES MAJOR BOTTLENECK IN CODE TIMING THE MORE VARIABLES YOU LOG***) fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t%.3f\t\t%.3f\t\t%.3f", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, pitchControlOutput1, rollControlOutput1, yawControlOutput1, thrustControlOutput1, cflieCopter1->radioRSSI(), euler[0], euler[1], euler[2], cflieCopter1->motor1(), cflieCopter1->motor2(), cflieCopter1->motor3(), cflieCopter1->motor4(), cflieCopter1->gyroX(), cflieCopter1->gyroY(), cflieCopter1->gyroZ()); // fprintf(out1, "\n"); #endif #endif #if 0 //(UNUSED) if (tcp_client_ON) { readMulticast(); //(argc < 1 = Listen Mode) // runTCPClient(); } #endif //cout << "PID Radio 2" << endl << endl; loopTime1End = cflieCopter1->currentTime() - initTime1; loopTime1 = loopTime1End - loopTime1Start; } else if(vrpnPacketBackup1 < 0){ //Failsafe so can't go below 0 (should never happen) | || (vrpnPacketBackup1 > 20)? vrpnPacketBackup1 = 0; } else if(vrpnPacketBackup1 >= 2){ vrpnPacketBackup1 --; // cout << "VRPN Packet Backup 1 Detected: " << vrpnPacketBackup1 << endl; }//End Packet Backup If check } //End Callback 1 </pre> </code> </blockquote> ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> e7cbea4809638111c1eaebb31e51f8c7c20c5717 Adding a Crazyflie 0 46 154 2016-07-28T17:45:13Z Jnoronha 3 added changes to vrpn cpp and h and eris_vrpn.cpp wikitext text/x-wiki Adding a Crazyflie to the Swarm is simple, but tedious. It's basically just replicating a copy of the other Crazyflies code, but there are multiple files you will need to make changes in. The following list should help you locate all the code you need to replicate: ==Changes in ''vrpn.cpp''== <blockquote> <code> <pre> vrpn_Tracker_Remote *tracker#; extern float xPositionDesired#; extern float yPositionDesired#; extern float zPositionDesired#; extern float yawDesired#; extern float xPosition#; extern float yPosition#; extern float zPosition#; extern CCrazyflie *cflieCopter#; extern double initTime#; extern char takeOff#; extern double takeOffTime#; void vrpn_init(std::string connectionName, void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback#)(void*, const vrpn_TRACKERCB), ......, char *key) { tracker# = new vrpn_Tracker_Remote("Crazyflie2#", connection); tracker#->register_change_handler(0, callback#); tracker#->mainloop(); </pre> </code> </blockquote> ===Changes in ''nearGround()''=== <blockquote> <code> <pre> void nearGround() //During Landing Mode checks how close to ground quad is for shutdown { ... ... ... if(cflieCopter#){ if((cflieCopter#->m_enumFlightMode == LANDING_MODE) && (zPosition# < 0.05)) { cflieCopter#->m_enumFlightMode = GROUNDED_MODE; } } } </pre> </code> </blockquote> ===Changes in ''updateHand()''=== <blockquote> <code> <pre> void updateHand() { if(handMode == 1) { // cout << "Hand Roll: " << rollHand << endl; if(killCount > 5){ ... ... cflieCopter#->m_enumFlightMode = GROUNDED_MODE; } else if(trackCount > 5){ ... ... cflieCopter#->m_enumFlightMode = HAND_MODE; } else{ ... ... if(zPositionHand > 1.6) { ... ... cflieCopter#->m_enumFlightMode = TAKEOFF_MODE; cout << "Hand Mode: Launching Quads" << endl; } else if(zPositionHand < 0.4) { ... ... cflieCopter#->m_enumFlightMode = LANDING_MODE; ... } } } } </pre> </code> </blockquote> ==Changes in ''vrpn.h''== <blockquote> <code> <pre> void vrpn_init(std::string connectionName, void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback#)(void*, const vrpn_TRACKERCB), ...., char *key); </pre> </code> </blockquote> ==Changes in ''eris_vrpn.cpp''== ===Global Variables=== <blockquote> <code> <pre> void VRPN_CALLBACK handle_Crazyflie#(void*, const vrpn_TRACKERCB t); CCrazyRadio *crRadio# = 0; //***NOT NECESSARY IF LESS THAN 3 QUADS PER RADIO*** CCrazyflie *cflieCopter# = 0; ControllerObject pidCtrl# = { 0 }; // init all fields to zero float rollControlOutput#; float pitchControlOutput#; float yawControlOutput#; float thrustControlOutput#; double initTime# = 0; int vrpnPacketBackup# = 0; double vrpnBackupTime# = 0; double vrpnBackupTime#Prev = 0; double vrpnBackupTime#Delta = 0; float xPositionDesired# = 0.681; float yPositionDesired# = 0.129; float zPositionDesired# = 0.6; float yawDesired# = -90.0; float yawDifference# = 0; float quadYaw# = 0; float prevQuadYaw# = 0; float camYawDeg# = 0; float camYawDeg#Off = 0; float quadYaw#Off = 0; float correctedYaw# = 0; float xError# = 0.0; float yError# = 0.0; float xStepPositionError# = 0.0; float yStepPositionError# = 0.0; float xPosition# = -0.012; float yPosition# = -0.008; //Default Crazyflie location setpoints float zPosition# = 0.75; char takeOff# = 0; double loopTime#Start = 0; double loopTime#End = 0; double loopTime# = 0; double loopTime#Prev = 0; double loopTime#Delta = 0; double vrpnPacketTime# = 0; double vrpnPacketTime#Prev = 0; double vrpnPacketDelta# = 0; FILE * out# = NULL; </pre> </code> </blockquote> ===Changes in ''main()''=== <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl# ); controllerInit( &pidCtrl# ); vrpn_init("192.168.0.120:3883", handle_pos, handle_Crazyflie2, handle_Crazyflie#, handle_Crazyflie(#+1), ..., &keystroke_now); cflieCopter# = new CCrazyflie(crRadio(radio dongle number), (Radio Channel)); const char * logHeader# = "#Crazyflie# Log File\n\ #Time\t\t........ if(cflieCopter#) { out# = fopen("cflie#.txt", "w"); if(out# == NULL) { printf("Could not open cflie#.log:errno %d\n", errno); exit(-1); } fprintf(out#, "%s\n", logHeader#); } crRadio#->setARDTime(2000); //Sets Wait Time between Packet Retries (**MUST BE IN INCREMENTS OF 250**) crRadio#->setARC(0); //Sets Number of times Retries Packet Send crRadio#->setPower(P_0DBM); cflieCopter#->setSendSetpoints( true ); initTime# = cflieCopter#->currentTime(); cflieCopter#->m_enumFlightMode = GROUNDED_MODE; fclose(out#); delete cflieCopter#; delete crRadio#; </pre> </code> </blockquote> ==Creating a New Callback== ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 717d18a6f7f0bd76e80ae2aaff790374ccf0ce6b 155 154 2016-07-28T17:51:50Z Jnoronha 3 /* Creating a New Callback */ added code and list of steps wikitext text/x-wiki Adding a Crazyflie to the Swarm is simple, but tedious. It's basically just replicating a copy of the other Crazyflies code, but there are multiple files you will need to make changes in. The following list should help you locate all the code you need to replicate: ==Changes in ''vrpn.cpp''== <blockquote> <code> <pre> vrpn_Tracker_Remote *tracker#; extern float xPositionDesired#; extern float yPositionDesired#; extern float zPositionDesired#; extern float yawDesired#; extern float xPosition#; extern float yPosition#; extern float zPosition#; extern CCrazyflie *cflieCopter#; extern double initTime#; extern char takeOff#; extern double takeOffTime#; void vrpn_init(std::string connectionName, void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback#)(void*, const vrpn_TRACKERCB), ......, char *key) { tracker# = new vrpn_Tracker_Remote("Crazyflie2#", connection); tracker#->register_change_handler(0, callback#); tracker#->mainloop(); </pre> </code> </blockquote> ===Changes in ''nearGround()''=== <blockquote> <code> <pre> void nearGround() //During Landing Mode checks how close to ground quad is for shutdown { ... ... ... if(cflieCopter#){ if((cflieCopter#->m_enumFlightMode == LANDING_MODE) && (zPosition# < 0.05)) { cflieCopter#->m_enumFlightMode = GROUNDED_MODE; } } } </pre> </code> </blockquote> ===Changes in ''updateHand()''=== <blockquote> <code> <pre> void updateHand() { if(handMode == 1) { // cout << "Hand Roll: " << rollHand << endl; if(killCount > 5){ ... ... cflieCopter#->m_enumFlightMode = GROUNDED_MODE; } else if(trackCount > 5){ ... ... cflieCopter#->m_enumFlightMode = HAND_MODE; } else{ ... ... if(zPositionHand > 1.6) { ... ... cflieCopter#->m_enumFlightMode = TAKEOFF_MODE; cout << "Hand Mode: Launching Quads" << endl; } else if(zPositionHand < 0.4) { ... ... cflieCopter#->m_enumFlightMode = LANDING_MODE; ... } } } } </pre> </code> </blockquote> ==Changes in ''vrpn.h''== <blockquote> <code> <pre> void vrpn_init(std::string connectionName, void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback#)(void*, const vrpn_TRACKERCB), ...., char *key); </pre> </code> </blockquote> ==Changes in ''eris_vrpn.cpp''== ===Global Variables=== <blockquote> <code> <pre> void VRPN_CALLBACK handle_Crazyflie#(void*, const vrpn_TRACKERCB t); CCrazyRadio *crRadio# = 0; //***NOT NECESSARY IF LESS THAN 3 QUADS PER RADIO*** CCrazyflie *cflieCopter# = 0; ControllerObject pidCtrl# = { 0 }; // init all fields to zero float rollControlOutput#; float pitchControlOutput#; float yawControlOutput#; float thrustControlOutput#; double initTime# = 0; int vrpnPacketBackup# = 0; double vrpnBackupTime# = 0; double vrpnBackupTime#Prev = 0; double vrpnBackupTime#Delta = 0; float xPositionDesired# = 0.681; float yPositionDesired# = 0.129; float zPositionDesired# = 0.6; float yawDesired# = -90.0; float yawDifference# = 0; float quadYaw# = 0; float prevQuadYaw# = 0; float camYawDeg# = 0; float camYawDeg#Off = 0; float quadYaw#Off = 0; float correctedYaw# = 0; float xError# = 0.0; float yError# = 0.0; float xStepPositionError# = 0.0; float yStepPositionError# = 0.0; float xPosition# = -0.012; float yPosition# = -0.008; //Default Crazyflie location setpoints float zPosition# = 0.75; char takeOff# = 0; double loopTime#Start = 0; double loopTime#End = 0; double loopTime# = 0; double loopTime#Prev = 0; double loopTime#Delta = 0; double vrpnPacketTime# = 0; double vrpnPacketTime#Prev = 0; double vrpnPacketDelta# = 0; FILE * out# = NULL; </pre> </code> </blockquote> ===Changes in ''main()''=== <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl# ); controllerInit( &pidCtrl# ); vrpn_init("192.168.0.120:3883", handle_pos, handle_Crazyflie2, handle_Crazyflie#, handle_Crazyflie(#+1), ..., &keystroke_now); cflieCopter# = new CCrazyflie(crRadio(radio dongle number), (Radio Channel)); const char * logHeader# = "#Crazyflie# Log File\n\ #Time\t\t........ if(cflieCopter#) { out# = fopen("cflie#.txt", "w"); if(out# == NULL) { printf("Could not open cflie#.log:errno %d\n", errno); exit(-1); } fprintf(out#, "%s\n", logHeader#); } crRadio#->setARDTime(2000); //Sets Wait Time between Packet Retries (**MUST BE IN INCREMENTS OF 250**) crRadio#->setARC(0); //Sets Number of times Retries Packet Send crRadio#->setPower(P_0DBM); cflieCopter#->setSendSetpoints( true ); initTime# = cflieCopter#->currentTime(); cflieCopter#->m_enumFlightMode = GROUNDED_MODE; fclose(out#); delete cflieCopter#; delete crRadio#; </pre> </code> </blockquote> ==Creating a New Callback== '''Note:''' To make it easier for this section you can: *COPY and PASTE the callback code directly after the last callback in the Swarm Client *Use FIND and REPLACE to replace all '#' signs with the Crazyflie number desired **'''IMPORTANT:''' Be careful, some of the '#' symbols are for the Radio Dongle number also. <blockquote> <code> <pre> void VRPN_CALLBACK handle_Crazyflie#(void*, const vrpn_TRACKERCB t) { if(vrpnPacketBackup# < 2) //If VRPN Buffer does NOT have old packets stored up, run main code { loopTime#Start = cflieCopter#->currentTime() - initTime#; loopTime#Delta = loopTime#Start - loopTime#Prev; //Calculates time difference between each loop start loopTime#Prev = loopTime#Start; vrpnPacketTime# = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnPacketDelta# = vrpnPacketTime# - vrpnPacketTime#Prev; vrpnPacketTime#Prev = vrpnPacketTime#; vrpnPacketBackup# = ceil(loopTime#Delta/vrpnPacketDelta#); //Calculates estimated # of packets built up in VRPN buffer. controllerSetAllDt(&pidCtrl#, vrpnPacketDelta#); //Variable dt for controller based on time between packets | vrpnPacketDelta2 cflieCopter1->cheat_process_packets(); //Flush out other Copter Packets crRadio(#RADIO NUM)->clearPackets(); crRadio(#RADIO NUM)->setChannel( cflieCopter#->radioChannel() ); frameCount++; // Get the euler angles q_vec_type euler; q_to_euler(euler, t.quat); xPosition# = t.pos[0]; yPosition# = t.pos[1]; //Stores X, Y, and Z Position for use in other Callbacks (external) zPosition# = -t.pos[2] + 0.05; #if USE_PRINTOUT cout << "PID Radio #" << endl << endl; #endif #if 0 //UNUSED (old way of storing camera data) //cout << "\033[2J\033[1;1H"; //Clears Terminal Window to display clean output cfliePitch = cflieCopter#->pitch(); cflieRoll = cflieCopter#->roll(); cflieYaw = cflieCopter#->yaw(); cflieThrust = cflieCopter#->thrust(); /* * Position * x t.pos[0] * y t.pos[1] * z t.pos[2] * * Orientation * yaw euler[0] Rotation * pitch euler[1] East-West movement * roll euler[2] North-South movement * Euler's range goes from -pi : +pi */ QUAD quad; quad.vrpnNow = 0; vrpn_data_t *vrpnData; vrpnData = (vrpn_data_t*) malloc(sizeof(vrpn_data_t)); vrpnData->usec = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnData->x = t.pos[0]; vrpnData->y = t.pos[1]; vrpnData->z = -t.pos[2] + 0.05; //Higher Altitude = Negative z //Added Offset for floor below camera system origin vrpnData->yaw = euler[0]; vrpnData->pitch = euler[1]; vrpnData->roll = euler[2]; xPosition# = t.pos[0]; yPosition# = t.pos[1]; zPosition# = -t.pos[2] + 0.05; cout << "xPosition of Crazyflie#: " << xPosition# << endl; quad.vrpnPrev = quad.vrpnNow; if (quad.vrpnNow == 0) { quad.vrpnPrev = 0; quad.vrpnTime0 = vrpnData->usec; quad.vrpnNow = vrpnData->usec; } else { quad.vrpnNow = vrpnData->usec - quad.vrpnTime0; } #endif //END UNUSED //==============YAW CORRECTION========================= (IMPORTANT!!!: YAW CONTROLLER INPUT IS INVERTED IN simple.cpp FILE***) camYawDeg# = -(euler[0] * 57.2958); //Converts From Radians TO Degrees quadYaw# = cflieCopter#->yaw(); if (frameCount == 50) { if (camYawDeg# < 0.0) camYawDeg#Off = camYawDeg# + 360.0; //Converts from +-180 to full 360 degree form else camYawDeg#Off = camYawDeg#; if(quadYaw# < 0.0) quadYaw#Off = quadYaw# + 360.0; else quadYaw#Off = quadYaw#; yawDifference# = quadYaw#Off - camYawDeg#Off; cout << "Yaw# Offset Taken: " << yawDifference# << endl; } correctedYaw# = camYawDeg# + yawDifference#; if(correctedYaw# > 180.0) correctedYaw# -= 360.0; else if(correctedYaw# < -180.0) correctedYaw# += 360.0; //===============END YAW CORRECTION========================= #if USE_PRINTOUT cout << "X: " << t.pos[0] << endl; cout << "Y: " << t.pos[1] << endl; cout << "Z: " << -t.pos[2] + 0.05 << endl; #endif #if USE_KEYBOARD if (cflieCopter#->m_enumFlightMode == LANDING_MODE) //Landing Mode (TODO Change to be a keystroke when implemented) { //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = xPositionDesired# - xPosition#; yError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, -0.4, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); takeOff# = 0; } else if (cflieCopter#->m_enumFlightMode == MIRROR_MODE) { //Acts as Master xPositionDesired# = -0.012; yPositionDesired# = -0.200; zPositionDesired# = 0.75; if( loopTime#Start - lastTime > 4.0 ) { toggle = !toggle; lastTime = loopTime#Start; } #if USE_PRINTOUT cout << "New xPositionDesired: " << xPositionDesired# << endl; #endif if(toggle) { xStepPositionError# = xPositionDesired# - xPosition#; yStepPositionError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xStepPositionError#, yStepPositionError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else { xStepPositionError# = (xPositionDesired# + 0.65) - xPosition#; yStepPositionError# = (yPositionDesired# + 0.65) - yPosition#; controllerSetXYError(&pidCtrl#, xStepPositionError#, yStepPositionError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired# + 0.65, yPositionDesired# + 0.65, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); //cout << "Toggled!" << endl; } } else if (cflieCopter#->m_enumFlightMode == TAKEOFF_MODE) { //correctedYaw# //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = xPositionDesired# - xPosition#; yError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else if (cflieCopter#->m_enumFlightMode == HAND_MODE) { //correctedYaw# //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = (xPositionHand - 0.5) - xPosition#; yError# = (yPositionHand + 0.5) - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else if(cflieCopter#->m_enumFlightMode == GROUNDED_MODE){ controllerResetAllPID(&pidCtrl#); rollControlOutput# = 0; pitchControlOutput# = 0; yawControlOutput# = 0; thrustControlOutput# = 0; } else{ //Emergency Case (Should never happen) controllerResetAllPID(&pidCtrl#); rollControlOutput# = 0; pitchControlOutput# = 0; yawControlOutput# = 0; thrustControlOutput# = 0; } #else controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], -t.pos[2], correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); #endif RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); #if USE_LOGGING #if USE_BASIC_LOGGING fprintf(out#, "%.6f\t\t", cflieCopter#->currentTime() - initTime# ); fprintf(out#, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter#->roll(), cflieCopter#->pitch(), quadYaw#, t.pos[0], t.pos[1], -t.pos[2], camYawDeg#, correctedYaw#, loopTimeTotal, loopTimeTotalDelta, loopTime#, loopTime#Delta, vrpnPacketDelta#, vrpnPacketTime#, vrpnPacketBackup#, cflieCopter#->radioRSSI()); // fprintf(out#, "\n"); #else fprintf(out#, "%.6f\t\t", cflieCopter#->currentTime() - initTime# ); fprintf(out#, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t%.3f\t\t%.3f\t\t%.3f", cflieCopter#->roll(), cflieCopter#->pitch(), quadYaw#, t.pos[0], t.pos[1], -t.pos[2], camYawDeg#, correctedYaw#, loopTimeTotal, loopTimeTotalDelta, loopTime#, loopTime#Delta, vrpnPacketDelta#, vrpnPacketTime#, vrpnPacketBackup#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, pitchControlOutput#, rollControlOutput#, yawControlOutput#, thrustControlOutput#, cflieCopter#->radioRSSI(), euler[0], euler[1], euler[2], cflieCopter#->motor1(), cflieCopter#->motor2(), cflieCopter#->motor3(), cflieCopter#->motor4(), cflieCopter#->gyroX(), cflieCopter#->gyroY(), cflieCopter#->gyroZ()); // fprintf(out#, "\n"); #endif #endif loopTime#End = cflieCopter#->currentTime() - initTime#; loopTime# = loopTime#End - loopTime#Start; } //End Packet Backup If check else if(vrpnPacketBackup# < 0){ //Failsafe so can't go below 0 (should never happen) | || (vrpnPacketBackup# > 20)? vrpnPacketBackup# = 0; // RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, // rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); } else if(vrpnPacketBackup# >= 2){ // cout << "VRPN Packet Backup # Detected: " << vrpnPacketBackup# << endl; vrpnPacketBackup# --; // RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, // rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); }//End Packet Backup Purge } //END CALLBACK # </pre> </code> </blockquote> ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 0321f11a2699e6da8d309359603f176e16fec31d 156 155 2016-07-28T17:52:37Z Jnoronha 3 /* Creating a New Callback */ change list to numbered list wikitext text/x-wiki Adding a Crazyflie to the Swarm is simple, but tedious. It's basically just replicating a copy of the other Crazyflies code, but there are multiple files you will need to make changes in. The following list should help you locate all the code you need to replicate: ==Changes in ''vrpn.cpp''== <blockquote> <code> <pre> vrpn_Tracker_Remote *tracker#; extern float xPositionDesired#; extern float yPositionDesired#; extern float zPositionDesired#; extern float yawDesired#; extern float xPosition#; extern float yPosition#; extern float zPosition#; extern CCrazyflie *cflieCopter#; extern double initTime#; extern char takeOff#; extern double takeOffTime#; void vrpn_init(std::string connectionName, void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback#)(void*, const vrpn_TRACKERCB), ......, char *key) { tracker# = new vrpn_Tracker_Remote("Crazyflie2#", connection); tracker#->register_change_handler(0, callback#); tracker#->mainloop(); </pre> </code> </blockquote> ===Changes in ''nearGround()''=== <blockquote> <code> <pre> void nearGround() //During Landing Mode checks how close to ground quad is for shutdown { ... ... ... if(cflieCopter#){ if((cflieCopter#->m_enumFlightMode == LANDING_MODE) && (zPosition# < 0.05)) { cflieCopter#->m_enumFlightMode = GROUNDED_MODE; } } } </pre> </code> </blockquote> ===Changes in ''updateHand()''=== <blockquote> <code> <pre> void updateHand() { if(handMode == 1) { // cout << "Hand Roll: " << rollHand << endl; if(killCount > 5){ ... ... cflieCopter#->m_enumFlightMode = GROUNDED_MODE; } else if(trackCount > 5){ ... ... cflieCopter#->m_enumFlightMode = HAND_MODE; } else{ ... ... if(zPositionHand > 1.6) { ... ... cflieCopter#->m_enumFlightMode = TAKEOFF_MODE; cout << "Hand Mode: Launching Quads" << endl; } else if(zPositionHand < 0.4) { ... ... cflieCopter#->m_enumFlightMode = LANDING_MODE; ... } } } } </pre> </code> </blockquote> ==Changes in ''vrpn.h''== <blockquote> <code> <pre> void vrpn_init(std::string connectionName, void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback#)(void*, const vrpn_TRACKERCB), ...., char *key); </pre> </code> </blockquote> ==Changes in ''eris_vrpn.cpp''== ===Global Variables=== <blockquote> <code> <pre> void VRPN_CALLBACK handle_Crazyflie#(void*, const vrpn_TRACKERCB t); CCrazyRadio *crRadio# = 0; //***NOT NECESSARY IF LESS THAN 3 QUADS PER RADIO*** CCrazyflie *cflieCopter# = 0; ControllerObject pidCtrl# = { 0 }; // init all fields to zero float rollControlOutput#; float pitchControlOutput#; float yawControlOutput#; float thrustControlOutput#; double initTime# = 0; int vrpnPacketBackup# = 0; double vrpnBackupTime# = 0; double vrpnBackupTime#Prev = 0; double vrpnBackupTime#Delta = 0; float xPositionDesired# = 0.681; float yPositionDesired# = 0.129; float zPositionDesired# = 0.6; float yawDesired# = -90.0; float yawDifference# = 0; float quadYaw# = 0; float prevQuadYaw# = 0; float camYawDeg# = 0; float camYawDeg#Off = 0; float quadYaw#Off = 0; float correctedYaw# = 0; float xError# = 0.0; float yError# = 0.0; float xStepPositionError# = 0.0; float yStepPositionError# = 0.0; float xPosition# = -0.012; float yPosition# = -0.008; //Default Crazyflie location setpoints float zPosition# = 0.75; char takeOff# = 0; double loopTime#Start = 0; double loopTime#End = 0; double loopTime# = 0; double loopTime#Prev = 0; double loopTime#Delta = 0; double vrpnPacketTime# = 0; double vrpnPacketTime#Prev = 0; double vrpnPacketDelta# = 0; FILE * out# = NULL; </pre> </code> </blockquote> ===Changes in ''main()''=== <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl# ); controllerInit( &pidCtrl# ); vrpn_init("192.168.0.120:3883", handle_pos, handle_Crazyflie2, handle_Crazyflie#, handle_Crazyflie(#+1), ..., &keystroke_now); cflieCopter# = new CCrazyflie(crRadio(radio dongle number), (Radio Channel)); const char * logHeader# = "#Crazyflie# Log File\n\ #Time\t\t........ if(cflieCopter#) { out# = fopen("cflie#.txt", "w"); if(out# == NULL) { printf("Could not open cflie#.log:errno %d\n", errno); exit(-1); } fprintf(out#, "%s\n", logHeader#); } crRadio#->setARDTime(2000); //Sets Wait Time between Packet Retries (**MUST BE IN INCREMENTS OF 250**) crRadio#->setARC(0); //Sets Number of times Retries Packet Send crRadio#->setPower(P_0DBM); cflieCopter#->setSendSetpoints( true ); initTime# = cflieCopter#->currentTime(); cflieCopter#->m_enumFlightMode = GROUNDED_MODE; fclose(out#); delete cflieCopter#; delete crRadio#; </pre> </code> </blockquote> ==Creating a New Callback== '''Note:''' To make it easier for this section you can: #COPY and PASTE the callback code directly after the last callback in the Swarm Client #Use FIND and REPLACE to replace all '#' signs with the Crazyflie number desired :*'''IMPORTANT:''' Be careful, some of the '#' symbols are used for the Radio Dongle number also. <blockquote> <code> <pre> void VRPN_CALLBACK handle_Crazyflie#(void*, const vrpn_TRACKERCB t) { if(vrpnPacketBackup# < 2) //If VRPN Buffer does NOT have old packets stored up, run main code { loopTime#Start = cflieCopter#->currentTime() - initTime#; loopTime#Delta = loopTime#Start - loopTime#Prev; //Calculates time difference between each loop start loopTime#Prev = loopTime#Start; vrpnPacketTime# = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnPacketDelta# = vrpnPacketTime# - vrpnPacketTime#Prev; vrpnPacketTime#Prev = vrpnPacketTime#; vrpnPacketBackup# = ceil(loopTime#Delta/vrpnPacketDelta#); //Calculates estimated # of packets built up in VRPN buffer. controllerSetAllDt(&pidCtrl#, vrpnPacketDelta#); //Variable dt for controller based on time between packets | vrpnPacketDelta2 cflieCopter1->cheat_process_packets(); //Flush out other Copter Packets crRadio(#RADIO NUM)->clearPackets(); crRadio(#RADIO NUM)->setChannel( cflieCopter#->radioChannel() ); frameCount++; // Get the euler angles q_vec_type euler; q_to_euler(euler, t.quat); xPosition# = t.pos[0]; yPosition# = t.pos[1]; //Stores X, Y, and Z Position for use in other Callbacks (external) zPosition# = -t.pos[2] + 0.05; #if USE_PRINTOUT cout << "PID Radio #" << endl << endl; #endif #if 0 //UNUSED (old way of storing camera data) //cout << "\033[2J\033[1;1H"; //Clears Terminal Window to display clean output cfliePitch = cflieCopter#->pitch(); cflieRoll = cflieCopter#->roll(); cflieYaw = cflieCopter#->yaw(); cflieThrust = cflieCopter#->thrust(); /* * Position * x t.pos[0] * y t.pos[1] * z t.pos[2] * * Orientation * yaw euler[0] Rotation * pitch euler[1] East-West movement * roll euler[2] North-South movement * Euler's range goes from -pi : +pi */ QUAD quad; quad.vrpnNow = 0; vrpn_data_t *vrpnData; vrpnData = (vrpn_data_t*) malloc(sizeof(vrpn_data_t)); vrpnData->usec = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnData->x = t.pos[0]; vrpnData->y = t.pos[1]; vrpnData->z = -t.pos[2] + 0.05; //Higher Altitude = Negative z //Added Offset for floor below camera system origin vrpnData->yaw = euler[0]; vrpnData->pitch = euler[1]; vrpnData->roll = euler[2]; xPosition# = t.pos[0]; yPosition# = t.pos[1]; zPosition# = -t.pos[2] + 0.05; cout << "xPosition of Crazyflie#: " << xPosition# << endl; quad.vrpnPrev = quad.vrpnNow; if (quad.vrpnNow == 0) { quad.vrpnPrev = 0; quad.vrpnTime0 = vrpnData->usec; quad.vrpnNow = vrpnData->usec; } else { quad.vrpnNow = vrpnData->usec - quad.vrpnTime0; } #endif //END UNUSED //==============YAW CORRECTION========================= (IMPORTANT!!!: YAW CONTROLLER INPUT IS INVERTED IN simple.cpp FILE***) camYawDeg# = -(euler[0] * 57.2958); //Converts From Radians TO Degrees quadYaw# = cflieCopter#->yaw(); if (frameCount == 50) { if (camYawDeg# < 0.0) camYawDeg#Off = camYawDeg# + 360.0; //Converts from +-180 to full 360 degree form else camYawDeg#Off = camYawDeg#; if(quadYaw# < 0.0) quadYaw#Off = quadYaw# + 360.0; else quadYaw#Off = quadYaw#; yawDifference# = quadYaw#Off - camYawDeg#Off; cout << "Yaw# Offset Taken: " << yawDifference# << endl; } correctedYaw# = camYawDeg# + yawDifference#; if(correctedYaw# > 180.0) correctedYaw# -= 360.0; else if(correctedYaw# < -180.0) correctedYaw# += 360.0; //===============END YAW CORRECTION========================= #if USE_PRINTOUT cout << "X: " << t.pos[0] << endl; cout << "Y: " << t.pos[1] << endl; cout << "Z: " << -t.pos[2] + 0.05 << endl; #endif #if USE_KEYBOARD if (cflieCopter#->m_enumFlightMode == LANDING_MODE) //Landing Mode (TODO Change to be a keystroke when implemented) { //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = xPositionDesired# - xPosition#; yError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, -0.4, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); takeOff# = 0; } else if (cflieCopter#->m_enumFlightMode == MIRROR_MODE) { //Acts as Master xPositionDesired# = -0.012; yPositionDesired# = -0.200; zPositionDesired# = 0.75; if( loopTime#Start - lastTime > 4.0 ) { toggle = !toggle; lastTime = loopTime#Start; } #if USE_PRINTOUT cout << "New xPositionDesired: " << xPositionDesired# << endl; #endif if(toggle) { xStepPositionError# = xPositionDesired# - xPosition#; yStepPositionError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xStepPositionError#, yStepPositionError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else { xStepPositionError# = (xPositionDesired# + 0.65) - xPosition#; yStepPositionError# = (yPositionDesired# + 0.65) - yPosition#; controllerSetXYError(&pidCtrl#, xStepPositionError#, yStepPositionError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired# + 0.65, yPositionDesired# + 0.65, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); //cout << "Toggled!" << endl; } } else if (cflieCopter#->m_enumFlightMode == TAKEOFF_MODE) { //correctedYaw# //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = xPositionDesired# - xPosition#; yError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else if (cflieCopter#->m_enumFlightMode == HAND_MODE) { //correctedYaw# //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = (xPositionHand - 0.5) - xPosition#; yError# = (yPositionHand + 0.5) - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else if(cflieCopter#->m_enumFlightMode == GROUNDED_MODE){ controllerResetAllPID(&pidCtrl#); rollControlOutput# = 0; pitchControlOutput# = 0; yawControlOutput# = 0; thrustControlOutput# = 0; } else{ //Emergency Case (Should never happen) controllerResetAllPID(&pidCtrl#); rollControlOutput# = 0; pitchControlOutput# = 0; yawControlOutput# = 0; thrustControlOutput# = 0; } #else controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], -t.pos[2], correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); #endif RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); #if USE_LOGGING #if USE_BASIC_LOGGING fprintf(out#, "%.6f\t\t", cflieCopter#->currentTime() - initTime# ); fprintf(out#, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter#->roll(), cflieCopter#->pitch(), quadYaw#, t.pos[0], t.pos[1], -t.pos[2], camYawDeg#, correctedYaw#, loopTimeTotal, loopTimeTotalDelta, loopTime#, loopTime#Delta, vrpnPacketDelta#, vrpnPacketTime#, vrpnPacketBackup#, cflieCopter#->radioRSSI()); // fprintf(out#, "\n"); #else fprintf(out#, "%.6f\t\t", cflieCopter#->currentTime() - initTime# ); fprintf(out#, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t%.3f\t\t%.3f\t\t%.3f", cflieCopter#->roll(), cflieCopter#->pitch(), quadYaw#, t.pos[0], t.pos[1], -t.pos[2], camYawDeg#, correctedYaw#, loopTimeTotal, loopTimeTotalDelta, loopTime#, loopTime#Delta, vrpnPacketDelta#, vrpnPacketTime#, vrpnPacketBackup#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, pitchControlOutput#, rollControlOutput#, yawControlOutput#, thrustControlOutput#, cflieCopter#->radioRSSI(), euler[0], euler[1], euler[2], cflieCopter#->motor1(), cflieCopter#->motor2(), cflieCopter#->motor3(), cflieCopter#->motor4(), cflieCopter#->gyroX(), cflieCopter#->gyroY(), cflieCopter#->gyroZ()); // fprintf(out#, "\n"); #endif #endif loopTime#End = cflieCopter#->currentTime() - initTime#; loopTime# = loopTime#End - loopTime#Start; } //End Packet Backup If check else if(vrpnPacketBackup# < 0){ //Failsafe so can't go below 0 (should never happen) | || (vrpnPacketBackup# > 20)? vrpnPacketBackup# = 0; // RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, // rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); } else if(vrpnPacketBackup# >= 2){ // cout << "VRPN Packet Backup # Detected: " << vrpnPacketBackup# << endl; vrpnPacketBackup# --; // RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, // rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); }//End Packet Backup Purge } //END CALLBACK # </pre> </code> </blockquote> ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 2194f1b889d2487f97ae72c46eeacc9fd6d3cdda 157 156 2016-07-28T17:53:31Z Jnoronha 3 Added ctrl+c handler section wikitext text/x-wiki Adding a Crazyflie to the Swarm is simple, but tedious. It's basically just replicating a copy of the other Crazyflies code, but there are multiple files you will need to make changes in. The following list should help you locate all the code you need to replicate: ==Changes in ''vrpn.cpp''== <blockquote> <code> <pre> vrpn_Tracker_Remote *tracker#; extern float xPositionDesired#; extern float yPositionDesired#; extern float zPositionDesired#; extern float yawDesired#; extern float xPosition#; extern float yPosition#; extern float zPosition#; extern CCrazyflie *cflieCopter#; extern double initTime#; extern char takeOff#; extern double takeOffTime#; void vrpn_init(std::string connectionName, void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback#)(void*, const vrpn_TRACKERCB), ......, char *key) { tracker# = new vrpn_Tracker_Remote("Crazyflie2#", connection); tracker#->register_change_handler(0, callback#); tracker#->mainloop(); </pre> </code> </blockquote> ===Changes in ''nearGround()''=== <blockquote> <code> <pre> void nearGround() //During Landing Mode checks how close to ground quad is for shutdown { ... ... ... if(cflieCopter#){ if((cflieCopter#->m_enumFlightMode == LANDING_MODE) && (zPosition# < 0.05)) { cflieCopter#->m_enumFlightMode = GROUNDED_MODE; } } } </pre> </code> </blockquote> ===Changes in ''updateHand()''=== <blockquote> <code> <pre> void updateHand() { if(handMode == 1) { // cout << "Hand Roll: " << rollHand << endl; if(killCount > 5){ ... ... cflieCopter#->m_enumFlightMode = GROUNDED_MODE; } else if(trackCount > 5){ ... ... cflieCopter#->m_enumFlightMode = HAND_MODE; } else{ ... ... if(zPositionHand > 1.6) { ... ... cflieCopter#->m_enumFlightMode = TAKEOFF_MODE; cout << "Hand Mode: Launching Quads" << endl; } else if(zPositionHand < 0.4) { ... ... cflieCopter#->m_enumFlightMode = LANDING_MODE; ... } } } } </pre> </code> </blockquote> ==Changes in ''vrpn.h''== <blockquote> <code> <pre> void vrpn_init(std::string connectionName, void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback#)(void*, const vrpn_TRACKERCB), ...., char *key); </pre> </code> </blockquote> ==Changes in ''eris_vrpn.cpp''== ===Global Variables=== <blockquote> <code> <pre> void VRPN_CALLBACK handle_Crazyflie#(void*, const vrpn_TRACKERCB t); CCrazyRadio *crRadio# = 0; //***NOT NECESSARY IF LESS THAN 3 QUADS PER RADIO*** CCrazyflie *cflieCopter# = 0; ControllerObject pidCtrl# = { 0 }; // init all fields to zero float rollControlOutput#; float pitchControlOutput#; float yawControlOutput#; float thrustControlOutput#; double initTime# = 0; int vrpnPacketBackup# = 0; double vrpnBackupTime# = 0; double vrpnBackupTime#Prev = 0; double vrpnBackupTime#Delta = 0; float xPositionDesired# = 0.681; float yPositionDesired# = 0.129; float zPositionDesired# = 0.6; float yawDesired# = -90.0; float yawDifference# = 0; float quadYaw# = 0; float prevQuadYaw# = 0; float camYawDeg# = 0; float camYawDeg#Off = 0; float quadYaw#Off = 0; float correctedYaw# = 0; float xError# = 0.0; float yError# = 0.0; float xStepPositionError# = 0.0; float yStepPositionError# = 0.0; float xPosition# = -0.012; float yPosition# = -0.008; //Default Crazyflie location setpoints float zPosition# = 0.75; char takeOff# = 0; double loopTime#Start = 0; double loopTime#End = 0; double loopTime# = 0; double loopTime#Prev = 0; double loopTime#Delta = 0; double vrpnPacketTime# = 0; double vrpnPacketTime#Prev = 0; double vrpnPacketDelta# = 0; FILE * out# = NULL; </pre> </code> </blockquote> ===Changes in ''main()''=== <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl# ); controllerInit( &pidCtrl# ); vrpn_init("192.168.0.120:3883", handle_pos, handle_Crazyflie2, handle_Crazyflie#, handle_Crazyflie(#+1), ..., &keystroke_now); cflieCopter# = new CCrazyflie(crRadio(radio dongle number), (Radio Channel)); const char * logHeader# = "#Crazyflie# Log File\n\ #Time\t\t........ if(cflieCopter#) { out# = fopen("cflie#.txt", "w"); if(out# == NULL) { printf("Could not open cflie#.log:errno %d\n", errno); exit(-1); } fprintf(out#, "%s\n", logHeader#); } crRadio#->setARDTime(2000); //Sets Wait Time between Packet Retries (**MUST BE IN INCREMENTS OF 250**) crRadio#->setARC(0); //Sets Number of times Retries Packet Send crRadio#->setPower(P_0DBM); cflieCopter#->setSendSetpoints( true ); initTime# = cflieCopter#->currentTime(); cflieCopter#->m_enumFlightMode = GROUNDED_MODE; fclose(out#); delete cflieCopter#; delete crRadio#; </pre> </code> </blockquote> ==Creating a New Callback== '''Note:''' To make it easier for this section you can: #COPY and PASTE the callback code directly after the last callback in the Swarm Client #Use FIND and REPLACE to replace all '#' signs with the Crazyflie number desired :*'''IMPORTANT:''' Be careful, some of the '#' symbols are used for the Radio Dongle number also. <blockquote> <code> <pre> void VRPN_CALLBACK handle_Crazyflie#(void*, const vrpn_TRACKERCB t) { if(vrpnPacketBackup# < 2) //If VRPN Buffer does NOT have old packets stored up, run main code { loopTime#Start = cflieCopter#->currentTime() - initTime#; loopTime#Delta = loopTime#Start - loopTime#Prev; //Calculates time difference between each loop start loopTime#Prev = loopTime#Start; vrpnPacketTime# = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnPacketDelta# = vrpnPacketTime# - vrpnPacketTime#Prev; vrpnPacketTime#Prev = vrpnPacketTime#; vrpnPacketBackup# = ceil(loopTime#Delta/vrpnPacketDelta#); //Calculates estimated # of packets built up in VRPN buffer. controllerSetAllDt(&pidCtrl#, vrpnPacketDelta#); //Variable dt for controller based on time between packets | vrpnPacketDelta2 cflieCopter1->cheat_process_packets(); //Flush out other Copter Packets crRadio(#RADIO NUM)->clearPackets(); crRadio(#RADIO NUM)->setChannel( cflieCopter#->radioChannel() ); frameCount++; // Get the euler angles q_vec_type euler; q_to_euler(euler, t.quat); xPosition# = t.pos[0]; yPosition# = t.pos[1]; //Stores X, Y, and Z Position for use in other Callbacks (external) zPosition# = -t.pos[2] + 0.05; #if USE_PRINTOUT cout << "PID Radio #" << endl << endl; #endif #if 0 //UNUSED (old way of storing camera data) //cout << "\033[2J\033[1;1H"; //Clears Terminal Window to display clean output cfliePitch = cflieCopter#->pitch(); cflieRoll = cflieCopter#->roll(); cflieYaw = cflieCopter#->yaw(); cflieThrust = cflieCopter#->thrust(); /* * Position * x t.pos[0] * y t.pos[1] * z t.pos[2] * * Orientation * yaw euler[0] Rotation * pitch euler[1] East-West movement * roll euler[2] North-South movement * Euler's range goes from -pi : +pi */ QUAD quad; quad.vrpnNow = 0; vrpn_data_t *vrpnData; vrpnData = (vrpn_data_t*) malloc(sizeof(vrpn_data_t)); vrpnData->usec = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnData->x = t.pos[0]; vrpnData->y = t.pos[1]; vrpnData->z = -t.pos[2] + 0.05; //Higher Altitude = Negative z //Added Offset for floor below camera system origin vrpnData->yaw = euler[0]; vrpnData->pitch = euler[1]; vrpnData->roll = euler[2]; xPosition# = t.pos[0]; yPosition# = t.pos[1]; zPosition# = -t.pos[2] + 0.05; cout << "xPosition of Crazyflie#: " << xPosition# << endl; quad.vrpnPrev = quad.vrpnNow; if (quad.vrpnNow == 0) { quad.vrpnPrev = 0; quad.vrpnTime0 = vrpnData->usec; quad.vrpnNow = vrpnData->usec; } else { quad.vrpnNow = vrpnData->usec - quad.vrpnTime0; } #endif //END UNUSED //==============YAW CORRECTION========================= (IMPORTANT!!!: YAW CONTROLLER INPUT IS INVERTED IN simple.cpp FILE***) camYawDeg# = -(euler[0] * 57.2958); //Converts From Radians TO Degrees quadYaw# = cflieCopter#->yaw(); if (frameCount == 50) { if (camYawDeg# < 0.0) camYawDeg#Off = camYawDeg# + 360.0; //Converts from +-180 to full 360 degree form else camYawDeg#Off = camYawDeg#; if(quadYaw# < 0.0) quadYaw#Off = quadYaw# + 360.0; else quadYaw#Off = quadYaw#; yawDifference# = quadYaw#Off - camYawDeg#Off; cout << "Yaw# Offset Taken: " << yawDifference# << endl; } correctedYaw# = camYawDeg# + yawDifference#; if(correctedYaw# > 180.0) correctedYaw# -= 360.0; else if(correctedYaw# < -180.0) correctedYaw# += 360.0; //===============END YAW CORRECTION========================= #if USE_PRINTOUT cout << "X: " << t.pos[0] << endl; cout << "Y: " << t.pos[1] << endl; cout << "Z: " << -t.pos[2] + 0.05 << endl; #endif #if USE_KEYBOARD if (cflieCopter#->m_enumFlightMode == LANDING_MODE) //Landing Mode (TODO Change to be a keystroke when implemented) { //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = xPositionDesired# - xPosition#; yError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, -0.4, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); takeOff# = 0; } else if (cflieCopter#->m_enumFlightMode == MIRROR_MODE) { //Acts as Master xPositionDesired# = -0.012; yPositionDesired# = -0.200; zPositionDesired# = 0.75; if( loopTime#Start - lastTime > 4.0 ) { toggle = !toggle; lastTime = loopTime#Start; } #if USE_PRINTOUT cout << "New xPositionDesired: " << xPositionDesired# << endl; #endif if(toggle) { xStepPositionError# = xPositionDesired# - xPosition#; yStepPositionError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xStepPositionError#, yStepPositionError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else { xStepPositionError# = (xPositionDesired# + 0.65) - xPosition#; yStepPositionError# = (yPositionDesired# + 0.65) - yPosition#; controllerSetXYError(&pidCtrl#, xStepPositionError#, yStepPositionError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired# + 0.65, yPositionDesired# + 0.65, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); //cout << "Toggled!" << endl; } } else if (cflieCopter#->m_enumFlightMode == TAKEOFF_MODE) { //correctedYaw# //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = xPositionDesired# - xPosition#; yError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else if (cflieCopter#->m_enumFlightMode == HAND_MODE) { //correctedYaw# //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = (xPositionHand - 0.5) - xPosition#; yError# = (yPositionHand + 0.5) - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else if(cflieCopter#->m_enumFlightMode == GROUNDED_MODE){ controllerResetAllPID(&pidCtrl#); rollControlOutput# = 0; pitchControlOutput# = 0; yawControlOutput# = 0; thrustControlOutput# = 0; } else{ //Emergency Case (Should never happen) controllerResetAllPID(&pidCtrl#); rollControlOutput# = 0; pitchControlOutput# = 0; yawControlOutput# = 0; thrustControlOutput# = 0; } #else controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], -t.pos[2], correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); #endif RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); #if USE_LOGGING #if USE_BASIC_LOGGING fprintf(out#, "%.6f\t\t", cflieCopter#->currentTime() - initTime# ); fprintf(out#, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter#->roll(), cflieCopter#->pitch(), quadYaw#, t.pos[0], t.pos[1], -t.pos[2], camYawDeg#, correctedYaw#, loopTimeTotal, loopTimeTotalDelta, loopTime#, loopTime#Delta, vrpnPacketDelta#, vrpnPacketTime#, vrpnPacketBackup#, cflieCopter#->radioRSSI()); // fprintf(out#, "\n"); #else fprintf(out#, "%.6f\t\t", cflieCopter#->currentTime() - initTime# ); fprintf(out#, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t%.3f\t\t%.3f\t\t%.3f", cflieCopter#->roll(), cflieCopter#->pitch(), quadYaw#, t.pos[0], t.pos[1], -t.pos[2], camYawDeg#, correctedYaw#, loopTimeTotal, loopTimeTotalDelta, loopTime#, loopTime#Delta, vrpnPacketDelta#, vrpnPacketTime#, vrpnPacketBackup#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, pitchControlOutput#, rollControlOutput#, yawControlOutput#, thrustControlOutput#, cflieCopter#->radioRSSI(), euler[0], euler[1], euler[2], cflieCopter#->motor1(), cflieCopter#->motor2(), cflieCopter#->motor3(), cflieCopter#->motor4(), cflieCopter#->gyroX(), cflieCopter#->gyroY(), cflieCopter#->gyroZ()); // fprintf(out#, "\n"); #endif #endif loopTime#End = cflieCopter#->currentTime() - initTime#; loopTime# = loopTime#End - loopTime#Start; } //End Packet Backup If check else if(vrpnPacketBackup# < 0){ //Failsafe so can't go below 0 (should never happen) | || (vrpnPacketBackup# > 20)? vrpnPacketBackup# = 0; // RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, // rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); } else if(vrpnPacketBackup# >= 2){ // cout << "VRPN Packet Backup # Detected: " << vrpnPacketBackup# << endl; vrpnPacketBackup# --; // RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, // rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); }//End Packet Backup Purge } //END CALLBACK # </pre> </code> </blockquote> ==Changes in CTRL+C Handler== ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 632a1af73c5a31f07bd48546458f3b0192b20fef 158 157 2016-07-28T17:57:14Z Jnoronha 3 /* Changes in CTRL+C Handler */ added changes wikitext text/x-wiki Adding a Crazyflie to the Swarm is simple, but tedious. It's basically just replicating a copy of the other Crazyflies code, but there are multiple files you will need to make changes in. The following list should help you locate all the code you need to replicate: ==Changes in ''vrpn.cpp''== <blockquote> <code> <pre> vrpn_Tracker_Remote *tracker#; extern float xPositionDesired#; extern float yPositionDesired#; extern float zPositionDesired#; extern float yawDesired#; extern float xPosition#; extern float yPosition#; extern float zPosition#; extern CCrazyflie *cflieCopter#; extern double initTime#; extern char takeOff#; extern double takeOffTime#; void vrpn_init(std::string connectionName, void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback#)(void*, const vrpn_TRACKERCB), ......, char *key) { tracker# = new vrpn_Tracker_Remote("Crazyflie2#", connection); tracker#->register_change_handler(0, callback#); tracker#->mainloop(); </pre> </code> </blockquote> ===Changes in ''nearGround()''=== <blockquote> <code> <pre> void nearGround() //During Landing Mode checks how close to ground quad is for shutdown { ... ... ... if(cflieCopter#){ if((cflieCopter#->m_enumFlightMode == LANDING_MODE) && (zPosition# < 0.05)) { cflieCopter#->m_enumFlightMode = GROUNDED_MODE; } } } </pre> </code> </blockquote> ===Changes in ''updateHand()''=== <blockquote> <code> <pre> void updateHand() { if(handMode == 1) { // cout << "Hand Roll: " << rollHand << endl; if(killCount > 5){ ... ... cflieCopter#->m_enumFlightMode = GROUNDED_MODE; } else if(trackCount > 5){ ... ... cflieCopter#->m_enumFlightMode = HAND_MODE; } else{ ... ... if(zPositionHand > 1.6) { ... ... cflieCopter#->m_enumFlightMode = TAKEOFF_MODE; cout << "Hand Mode: Launching Quads" << endl; } else if(zPositionHand < 0.4) { ... ... cflieCopter#->m_enumFlightMode = LANDING_MODE; ... } } } } </pre> </code> </blockquote> ==Changes in ''vrpn.h''== <blockquote> <code> <pre> void vrpn_init(std::string connectionName, void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback#)(void*, const vrpn_TRACKERCB), ...., char *key); </pre> </code> </blockquote> ==Changes in ''eris_vrpn.cpp''== ===Global Variables=== <blockquote> <code> <pre> void VRPN_CALLBACK handle_Crazyflie#(void*, const vrpn_TRACKERCB t); CCrazyRadio *crRadio# = 0; //***NOT NECESSARY IF LESS THAN 3 QUADS PER RADIO*** CCrazyflie *cflieCopter# = 0; ControllerObject pidCtrl# = { 0 }; // init all fields to zero float rollControlOutput#; float pitchControlOutput#; float yawControlOutput#; float thrustControlOutput#; double initTime# = 0; int vrpnPacketBackup# = 0; double vrpnBackupTime# = 0; double vrpnBackupTime#Prev = 0; double vrpnBackupTime#Delta = 0; float xPositionDesired# = 0.681; float yPositionDesired# = 0.129; float zPositionDesired# = 0.6; float yawDesired# = -90.0; float yawDifference# = 0; float quadYaw# = 0; float prevQuadYaw# = 0; float camYawDeg# = 0; float camYawDeg#Off = 0; float quadYaw#Off = 0; float correctedYaw# = 0; float xError# = 0.0; float yError# = 0.0; float xStepPositionError# = 0.0; float yStepPositionError# = 0.0; float xPosition# = -0.012; float yPosition# = -0.008; //Default Crazyflie location setpoints float zPosition# = 0.75; char takeOff# = 0; double loopTime#Start = 0; double loopTime#End = 0; double loopTime# = 0; double loopTime#Prev = 0; double loopTime#Delta = 0; double vrpnPacketTime# = 0; double vrpnPacketTime#Prev = 0; double vrpnPacketDelta# = 0; FILE * out# = NULL; </pre> </code> </blockquote> ===Changes in ''main()''=== <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl# ); controllerInit( &pidCtrl# ); vrpn_init("192.168.0.120:3883", handle_pos, handle_Crazyflie2, handle_Crazyflie#, handle_Crazyflie(#+1), ..., &keystroke_now); cflieCopter# = new CCrazyflie(crRadio(radio dongle number), (Radio Channel)); const char * logHeader# = "#Crazyflie# Log File\n\ #Time\t\t........ if(cflieCopter#) { out# = fopen("cflie#.txt", "w"); if(out# == NULL) { printf("Could not open cflie#.log:errno %d\n", errno); exit(-1); } fprintf(out#, "%s\n", logHeader#); } crRadio#->setARDTime(2000); //Sets Wait Time between Packet Retries (**MUST BE IN INCREMENTS OF 250**) crRadio#->setARC(0); //Sets Number of times Retries Packet Send crRadio#->setPower(P_0DBM); cflieCopter#->setSendSetpoints( true ); initTime# = cflieCopter#->currentTime(); cflieCopter#->m_enumFlightMode = GROUNDED_MODE; fclose(out#); delete cflieCopter#; delete crRadio#; </pre> </code> </blockquote> ==Creating a New Callback== '''Note:''' To make it easier for this section you can: #COPY and PASTE the callback code directly after the last callback in the Swarm Client #Use FIND and REPLACE to replace all '#' signs with the Crazyflie number desired :*'''IMPORTANT:''' Be careful, some of the '#' symbols are used for the Radio Dongle number also. <blockquote> <code> <pre> void VRPN_CALLBACK handle_Crazyflie#(void*, const vrpn_TRACKERCB t) { if(vrpnPacketBackup# < 2) //If VRPN Buffer does NOT have old packets stored up, run main code { loopTime#Start = cflieCopter#->currentTime() - initTime#; loopTime#Delta = loopTime#Start - loopTime#Prev; //Calculates time difference between each loop start loopTime#Prev = loopTime#Start; vrpnPacketTime# = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnPacketDelta# = vrpnPacketTime# - vrpnPacketTime#Prev; vrpnPacketTime#Prev = vrpnPacketTime#; vrpnPacketBackup# = ceil(loopTime#Delta/vrpnPacketDelta#); //Calculates estimated # of packets built up in VRPN buffer. controllerSetAllDt(&pidCtrl#, vrpnPacketDelta#); //Variable dt for controller based on time between packets | vrpnPacketDelta2 cflieCopter1->cheat_process_packets(); //Flush out other Copter Packets crRadio(#RADIO NUM)->clearPackets(); crRadio(#RADIO NUM)->setChannel( cflieCopter#->radioChannel() ); frameCount++; // Get the euler angles q_vec_type euler; q_to_euler(euler, t.quat); xPosition# = t.pos[0]; yPosition# = t.pos[1]; //Stores X, Y, and Z Position for use in other Callbacks (external) zPosition# = -t.pos[2] + 0.05; #if USE_PRINTOUT cout << "PID Radio #" << endl << endl; #endif #if 0 //UNUSED (old way of storing camera data) //cout << "\033[2J\033[1;1H"; //Clears Terminal Window to display clean output cfliePitch = cflieCopter#->pitch(); cflieRoll = cflieCopter#->roll(); cflieYaw = cflieCopter#->yaw(); cflieThrust = cflieCopter#->thrust(); /* * Position * x t.pos[0] * y t.pos[1] * z t.pos[2] * * Orientation * yaw euler[0] Rotation * pitch euler[1] East-West movement * roll euler[2] North-South movement * Euler's range goes from -pi : +pi */ QUAD quad; quad.vrpnNow = 0; vrpn_data_t *vrpnData; vrpnData = (vrpn_data_t*) malloc(sizeof(vrpn_data_t)); vrpnData->usec = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnData->x = t.pos[0]; vrpnData->y = t.pos[1]; vrpnData->z = -t.pos[2] + 0.05; //Higher Altitude = Negative z //Added Offset for floor below camera system origin vrpnData->yaw = euler[0]; vrpnData->pitch = euler[1]; vrpnData->roll = euler[2]; xPosition# = t.pos[0]; yPosition# = t.pos[1]; zPosition# = -t.pos[2] + 0.05; cout << "xPosition of Crazyflie#: " << xPosition# << endl; quad.vrpnPrev = quad.vrpnNow; if (quad.vrpnNow == 0) { quad.vrpnPrev = 0; quad.vrpnTime0 = vrpnData->usec; quad.vrpnNow = vrpnData->usec; } else { quad.vrpnNow = vrpnData->usec - quad.vrpnTime0; } #endif //END UNUSED //==============YAW CORRECTION========================= (IMPORTANT!!!: YAW CONTROLLER INPUT IS INVERTED IN simple.cpp FILE***) camYawDeg# = -(euler[0] * 57.2958); //Converts From Radians TO Degrees quadYaw# = cflieCopter#->yaw(); if (frameCount == 50) { if (camYawDeg# < 0.0) camYawDeg#Off = camYawDeg# + 360.0; //Converts from +-180 to full 360 degree form else camYawDeg#Off = camYawDeg#; if(quadYaw# < 0.0) quadYaw#Off = quadYaw# + 360.0; else quadYaw#Off = quadYaw#; yawDifference# = quadYaw#Off - camYawDeg#Off; cout << "Yaw# Offset Taken: " << yawDifference# << endl; } correctedYaw# = camYawDeg# + yawDifference#; if(correctedYaw# > 180.0) correctedYaw# -= 360.0; else if(correctedYaw# < -180.0) correctedYaw# += 360.0; //===============END YAW CORRECTION========================= #if USE_PRINTOUT cout << "X: " << t.pos[0] << endl; cout << "Y: " << t.pos[1] << endl; cout << "Z: " << -t.pos[2] + 0.05 << endl; #endif #if USE_KEYBOARD if (cflieCopter#->m_enumFlightMode == LANDING_MODE) //Landing Mode (TODO Change to be a keystroke when implemented) { //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = xPositionDesired# - xPosition#; yError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, -0.4, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); takeOff# = 0; } else if (cflieCopter#->m_enumFlightMode == MIRROR_MODE) { //Acts as Master xPositionDesired# = -0.012; yPositionDesired# = -0.200; zPositionDesired# = 0.75; if( loopTime#Start - lastTime > 4.0 ) { toggle = !toggle; lastTime = loopTime#Start; } #if USE_PRINTOUT cout << "New xPositionDesired: " << xPositionDesired# << endl; #endif if(toggle) { xStepPositionError# = xPositionDesired# - xPosition#; yStepPositionError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xStepPositionError#, yStepPositionError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else { xStepPositionError# = (xPositionDesired# + 0.65) - xPosition#; yStepPositionError# = (yPositionDesired# + 0.65) - yPosition#; controllerSetXYError(&pidCtrl#, xStepPositionError#, yStepPositionError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired# + 0.65, yPositionDesired# + 0.65, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); //cout << "Toggled!" << endl; } } else if (cflieCopter#->m_enumFlightMode == TAKEOFF_MODE) { //correctedYaw# //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = xPositionDesired# - xPosition#; yError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else if (cflieCopter#->m_enumFlightMode == HAND_MODE) { //correctedYaw# //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = (xPositionHand - 0.5) - xPosition#; yError# = (yPositionHand + 0.5) - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else if(cflieCopter#->m_enumFlightMode == GROUNDED_MODE){ controllerResetAllPID(&pidCtrl#); rollControlOutput# = 0; pitchControlOutput# = 0; yawControlOutput# = 0; thrustControlOutput# = 0; } else{ //Emergency Case (Should never happen) controllerResetAllPID(&pidCtrl#); rollControlOutput# = 0; pitchControlOutput# = 0; yawControlOutput# = 0; thrustControlOutput# = 0; } #else controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], -t.pos[2], correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); #endif RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); #if USE_LOGGING #if USE_BASIC_LOGGING fprintf(out#, "%.6f\t\t", cflieCopter#->currentTime() - initTime# ); fprintf(out#, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter#->roll(), cflieCopter#->pitch(), quadYaw#, t.pos[0], t.pos[1], -t.pos[2], camYawDeg#, correctedYaw#, loopTimeTotal, loopTimeTotalDelta, loopTime#, loopTime#Delta, vrpnPacketDelta#, vrpnPacketTime#, vrpnPacketBackup#, cflieCopter#->radioRSSI()); // fprintf(out#, "\n"); #else fprintf(out#, "%.6f\t\t", cflieCopter#->currentTime() - initTime# ); fprintf(out#, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t%.3f\t\t%.3f\t\t%.3f", cflieCopter#->roll(), cflieCopter#->pitch(), quadYaw#, t.pos[0], t.pos[1], -t.pos[2], camYawDeg#, correctedYaw#, loopTimeTotal, loopTimeTotalDelta, loopTime#, loopTime#Delta, vrpnPacketDelta#, vrpnPacketTime#, vrpnPacketBackup#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, pitchControlOutput#, rollControlOutput#, yawControlOutput#, thrustControlOutput#, cflieCopter#->radioRSSI(), euler[0], euler[1], euler[2], cflieCopter#->motor1(), cflieCopter#->motor2(), cflieCopter#->motor3(), cflieCopter#->motor4(), cflieCopter#->gyroX(), cflieCopter#->gyroY(), cflieCopter#->gyroZ()); // fprintf(out#, "\n"); #endif #endif loopTime#End = cflieCopter#->currentTime() - initTime#; loopTime# = loopTime#End - loopTime#Start; } //End Packet Backup If check else if(vrpnPacketBackup# < 0){ //Failsafe so can't go below 0 (should never happen) | || (vrpnPacketBackup# > 20)? vrpnPacketBackup# = 0; // RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, // rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); } else if(vrpnPacketBackup# >= 2){ // cout << "VRPN Packet Backup # Detected: " << vrpnPacketBackup# << endl; vrpnPacketBackup# --; // RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, // rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); }//End Packet Backup Purge } //END CALLBACK # </pre> </code> </blockquote> ==Changes in CTRL+C Handler== <blockquote> <code> <pre> cflieCopter#->setThrust(10000); cout << "Battery#: " << cflieCopter#->batteryLevel() << endl; cflieCopter#->cycle(); #if USE_LOGGING ... ... ... fclose(out#); #endif delete cflieCopter#; delete crRadio#; </pre> </code> </blockquote> ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 4ccbd3921772b66a3a5e66cb5743c774a91740d8 159 158 2016-07-28T17:59:28Z Jnoronha 3 changed callback and ctrl+c heading levels to be inside of eris_vrpn changes wikitext text/x-wiki Adding a Crazyflie to the Swarm is simple, but tedious. It's basically just replicating a copy of the other Crazyflies code, but there are multiple files you will need to make changes in. The following list should help you locate all the code you need to replicate: ==Changes in ''vrpn.cpp''== <blockquote> <code> <pre> vrpn_Tracker_Remote *tracker#; extern float xPositionDesired#; extern float yPositionDesired#; extern float zPositionDesired#; extern float yawDesired#; extern float xPosition#; extern float yPosition#; extern float zPosition#; extern CCrazyflie *cflieCopter#; extern double initTime#; extern char takeOff#; extern double takeOffTime#; void vrpn_init(std::string connectionName, void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback#)(void*, const vrpn_TRACKERCB), ......, char *key) { tracker# = new vrpn_Tracker_Remote("Crazyflie2#", connection); tracker#->register_change_handler(0, callback#); tracker#->mainloop(); </pre> </code> </blockquote> ===Changes in ''nearGround()''=== <blockquote> <code> <pre> void nearGround() //During Landing Mode checks how close to ground quad is for shutdown { ... ... ... if(cflieCopter#){ if((cflieCopter#->m_enumFlightMode == LANDING_MODE) && (zPosition# < 0.05)) { cflieCopter#->m_enumFlightMode = GROUNDED_MODE; } } } </pre> </code> </blockquote> ===Changes in ''updateHand()''=== <blockquote> <code> <pre> void updateHand() { if(handMode == 1) { // cout << "Hand Roll: " << rollHand << endl; if(killCount > 5){ ... ... cflieCopter#->m_enumFlightMode = GROUNDED_MODE; } else if(trackCount > 5){ ... ... cflieCopter#->m_enumFlightMode = HAND_MODE; } else{ ... ... if(zPositionHand > 1.6) { ... ... cflieCopter#->m_enumFlightMode = TAKEOFF_MODE; cout << "Hand Mode: Launching Quads" << endl; } else if(zPositionHand < 0.4) { ... ... cflieCopter#->m_enumFlightMode = LANDING_MODE; ... } } } } </pre> </code> </blockquote> ==Changes in ''vrpn.h''== <blockquote> <code> <pre> void vrpn_init(std::string connectionName, void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback#)(void*, const vrpn_TRACKERCB), ...., char *key); </pre> </code> </blockquote> ==Changes in ''eris_vrpn.cpp''== ===Global Variables=== <blockquote> <code> <pre> void VRPN_CALLBACK handle_Crazyflie#(void*, const vrpn_TRACKERCB t); CCrazyRadio *crRadio# = 0; //***NOT NECESSARY IF LESS THAN 3 QUADS PER RADIO*** CCrazyflie *cflieCopter# = 0; ControllerObject pidCtrl# = { 0 }; // init all fields to zero float rollControlOutput#; float pitchControlOutput#; float yawControlOutput#; float thrustControlOutput#; double initTime# = 0; int vrpnPacketBackup# = 0; double vrpnBackupTime# = 0; double vrpnBackupTime#Prev = 0; double vrpnBackupTime#Delta = 0; float xPositionDesired# = 0.681; float yPositionDesired# = 0.129; float zPositionDesired# = 0.6; float yawDesired# = -90.0; float yawDifference# = 0; float quadYaw# = 0; float prevQuadYaw# = 0; float camYawDeg# = 0; float camYawDeg#Off = 0; float quadYaw#Off = 0; float correctedYaw# = 0; float xError# = 0.0; float yError# = 0.0; float xStepPositionError# = 0.0; float yStepPositionError# = 0.0; float xPosition# = -0.012; float yPosition# = -0.008; //Default Crazyflie location setpoints float zPosition# = 0.75; char takeOff# = 0; double loopTime#Start = 0; double loopTime#End = 0; double loopTime# = 0; double loopTime#Prev = 0; double loopTime#Delta = 0; double vrpnPacketTime# = 0; double vrpnPacketTime#Prev = 0; double vrpnPacketDelta# = 0; FILE * out# = NULL; </pre> </code> </blockquote> ===Changes in ''main()''=== <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl# ); controllerInit( &pidCtrl# ); vrpn_init("192.168.0.120:3883", handle_pos, handle_Crazyflie2, handle_Crazyflie#, handle_Crazyflie(#+1), ..., &keystroke_now); cflieCopter# = new CCrazyflie(crRadio(radio dongle number), (Radio Channel)); const char * logHeader# = "#Crazyflie# Log File\n\ #Time\t\t........ if(cflieCopter#) { out# = fopen("cflie#.txt", "w"); if(out# == NULL) { printf("Could not open cflie#.log:errno %d\n", errno); exit(-1); } fprintf(out#, "%s\n", logHeader#); } crRadio#->setARDTime(2000); //Sets Wait Time between Packet Retries (**MUST BE IN INCREMENTS OF 250**) crRadio#->setARC(0); //Sets Number of times Retries Packet Send crRadio#->setPower(P_0DBM); cflieCopter#->setSendSetpoints( true ); initTime# = cflieCopter#->currentTime(); cflieCopter#->m_enumFlightMode = GROUNDED_MODE; fclose(out#); delete cflieCopter#; delete crRadio#; </pre> </code> </blockquote> ===Create a New Callback=== '''Note:''' To make it easier for this section you can: #COPY and PASTE the callback code directly after the last callback in the Swarm Client #Use FIND and REPLACE to replace all '#' signs with the Crazyflie number desired :*'''IMPORTANT:''' Be careful, some of the '#' symbols are used for the Radio Dongle number also. <blockquote> <code> <pre> void VRPN_CALLBACK handle_Crazyflie#(void*, const vrpn_TRACKERCB t) { if(vrpnPacketBackup# < 2) //If VRPN Buffer does NOT have old packets stored up, run main code { loopTime#Start = cflieCopter#->currentTime() - initTime#; loopTime#Delta = loopTime#Start - loopTime#Prev; //Calculates time difference between each loop start loopTime#Prev = loopTime#Start; vrpnPacketTime# = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnPacketDelta# = vrpnPacketTime# - vrpnPacketTime#Prev; vrpnPacketTime#Prev = vrpnPacketTime#; vrpnPacketBackup# = ceil(loopTime#Delta/vrpnPacketDelta#); //Calculates estimated # of packets built up in VRPN buffer. controllerSetAllDt(&pidCtrl#, vrpnPacketDelta#); //Variable dt for controller based on time between packets | vrpnPacketDelta2 cflieCopter1->cheat_process_packets(); //Flush out other Copter Packets crRadio(#RADIO NUM)->clearPackets(); crRadio(#RADIO NUM)->setChannel( cflieCopter#->radioChannel() ); frameCount++; // Get the euler angles q_vec_type euler; q_to_euler(euler, t.quat); xPosition# = t.pos[0]; yPosition# = t.pos[1]; //Stores X, Y, and Z Position for use in other Callbacks (external) zPosition# = -t.pos[2] + 0.05; #if USE_PRINTOUT cout << "PID Radio #" << endl << endl; #endif #if 0 //UNUSED (old way of storing camera data) //cout << "\033[2J\033[1;1H"; //Clears Terminal Window to display clean output cfliePitch = cflieCopter#->pitch(); cflieRoll = cflieCopter#->roll(); cflieYaw = cflieCopter#->yaw(); cflieThrust = cflieCopter#->thrust(); /* * Position * x t.pos[0] * y t.pos[1] * z t.pos[2] * * Orientation * yaw euler[0] Rotation * pitch euler[1] East-West movement * roll euler[2] North-South movement * Euler's range goes from -pi : +pi */ QUAD quad; quad.vrpnNow = 0; vrpn_data_t *vrpnData; vrpnData = (vrpn_data_t*) malloc(sizeof(vrpn_data_t)); vrpnData->usec = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnData->x = t.pos[0]; vrpnData->y = t.pos[1]; vrpnData->z = -t.pos[2] + 0.05; //Higher Altitude = Negative z //Added Offset for floor below camera system origin vrpnData->yaw = euler[0]; vrpnData->pitch = euler[1]; vrpnData->roll = euler[2]; xPosition# = t.pos[0]; yPosition# = t.pos[1]; zPosition# = -t.pos[2] + 0.05; cout << "xPosition of Crazyflie#: " << xPosition# << endl; quad.vrpnPrev = quad.vrpnNow; if (quad.vrpnNow == 0) { quad.vrpnPrev = 0; quad.vrpnTime0 = vrpnData->usec; quad.vrpnNow = vrpnData->usec; } else { quad.vrpnNow = vrpnData->usec - quad.vrpnTime0; } #endif //END UNUSED //==============YAW CORRECTION========================= (IMPORTANT!!!: YAW CONTROLLER INPUT IS INVERTED IN simple.cpp FILE***) camYawDeg# = -(euler[0] * 57.2958); //Converts From Radians TO Degrees quadYaw# = cflieCopter#->yaw(); if (frameCount == 50) { if (camYawDeg# < 0.0) camYawDeg#Off = camYawDeg# + 360.0; //Converts from +-180 to full 360 degree form else camYawDeg#Off = camYawDeg#; if(quadYaw# < 0.0) quadYaw#Off = quadYaw# + 360.0; else quadYaw#Off = quadYaw#; yawDifference# = quadYaw#Off - camYawDeg#Off; cout << "Yaw# Offset Taken: " << yawDifference# << endl; } correctedYaw# = camYawDeg# + yawDifference#; if(correctedYaw# > 180.0) correctedYaw# -= 360.0; else if(correctedYaw# < -180.0) correctedYaw# += 360.0; //===============END YAW CORRECTION========================= #if USE_PRINTOUT cout << "X: " << t.pos[0] << endl; cout << "Y: " << t.pos[1] << endl; cout << "Z: " << -t.pos[2] + 0.05 << endl; #endif #if USE_KEYBOARD if (cflieCopter#->m_enumFlightMode == LANDING_MODE) //Landing Mode (TODO Change to be a keystroke when implemented) { //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = xPositionDesired# - xPosition#; yError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, -0.4, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); takeOff# = 0; } else if (cflieCopter#->m_enumFlightMode == MIRROR_MODE) { //Acts as Master xPositionDesired# = -0.012; yPositionDesired# = -0.200; zPositionDesired# = 0.75; if( loopTime#Start - lastTime > 4.0 ) { toggle = !toggle; lastTime = loopTime#Start; } #if USE_PRINTOUT cout << "New xPositionDesired: " << xPositionDesired# << endl; #endif if(toggle) { xStepPositionError# = xPositionDesired# - xPosition#; yStepPositionError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xStepPositionError#, yStepPositionError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else { xStepPositionError# = (xPositionDesired# + 0.65) - xPosition#; yStepPositionError# = (yPositionDesired# + 0.65) - yPosition#; controllerSetXYError(&pidCtrl#, xStepPositionError#, yStepPositionError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired# + 0.65, yPositionDesired# + 0.65, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); //cout << "Toggled!" << endl; } } else if (cflieCopter#->m_enumFlightMode == TAKEOFF_MODE) { //correctedYaw# //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = xPositionDesired# - xPosition#; yError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else if (cflieCopter#->m_enumFlightMode == HAND_MODE) { //correctedYaw# //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = (xPositionHand - 0.5) - xPosition#; yError# = (yPositionHand + 0.5) - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else if(cflieCopter#->m_enumFlightMode == GROUNDED_MODE){ controllerResetAllPID(&pidCtrl#); rollControlOutput# = 0; pitchControlOutput# = 0; yawControlOutput# = 0; thrustControlOutput# = 0; } else{ //Emergency Case (Should never happen) controllerResetAllPID(&pidCtrl#); rollControlOutput# = 0; pitchControlOutput# = 0; yawControlOutput# = 0; thrustControlOutput# = 0; } #else controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], -t.pos[2], correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); #endif RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); #if USE_LOGGING #if USE_BASIC_LOGGING fprintf(out#, "%.6f\t\t", cflieCopter#->currentTime() - initTime# ); fprintf(out#, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter#->roll(), cflieCopter#->pitch(), quadYaw#, t.pos[0], t.pos[1], -t.pos[2], camYawDeg#, correctedYaw#, loopTimeTotal, loopTimeTotalDelta, loopTime#, loopTime#Delta, vrpnPacketDelta#, vrpnPacketTime#, vrpnPacketBackup#, cflieCopter#->radioRSSI()); // fprintf(out#, "\n"); #else fprintf(out#, "%.6f\t\t", cflieCopter#->currentTime() - initTime# ); fprintf(out#, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t%.3f\t\t%.3f\t\t%.3f", cflieCopter#->roll(), cflieCopter#->pitch(), quadYaw#, t.pos[0], t.pos[1], -t.pos[2], camYawDeg#, correctedYaw#, loopTimeTotal, loopTimeTotalDelta, loopTime#, loopTime#Delta, vrpnPacketDelta#, vrpnPacketTime#, vrpnPacketBackup#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, pitchControlOutput#, rollControlOutput#, yawControlOutput#, thrustControlOutput#, cflieCopter#->radioRSSI(), euler[0], euler[1], euler[2], cflieCopter#->motor1(), cflieCopter#->motor2(), cflieCopter#->motor3(), cflieCopter#->motor4(), cflieCopter#->gyroX(), cflieCopter#->gyroY(), cflieCopter#->gyroZ()); // fprintf(out#, "\n"); #endif #endif loopTime#End = cflieCopter#->currentTime() - initTime#; loopTime# = loopTime#End - loopTime#Start; } //End Packet Backup If check else if(vrpnPacketBackup# < 0){ //Failsafe so can't go below 0 (should never happen) | || (vrpnPacketBackup# > 20)? vrpnPacketBackup# = 0; // RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, // rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); } else if(vrpnPacketBackup# >= 2){ // cout << "VRPN Packet Backup # Detected: " << vrpnPacketBackup# << endl; vrpnPacketBackup# --; // RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, // rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); }//End Packet Backup Purge } //END CALLBACK # </pre> </code> </blockquote> ===Changes in CTRL+C Handler=== <blockquote> <code> <pre> cflieCopter#->setThrust(10000); cout << "Battery#: " << cflieCopter#->batteryLevel() << endl; cflieCopter#->cycle(); #if USE_LOGGING ... ... ... fclose(out#); #endif delete cflieCopter#; delete crRadio#; </pre> </code> </blockquote> ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 6c39e458cc2693677fa3aae22b96b80eb1b95d58 160 159 2016-07-28T18:00:09Z Jnoronha 3 punctuation wikitext text/x-wiki Adding a Crazyflie to the Swarm is simple, but tedious. It's basically just replicating a copy of the other Crazyflie's code, but there are multiple files you will need to make changes in. The following list should help you locate all the code you need to replicate: ==Changes in ''vrpn.cpp''== <blockquote> <code> <pre> vrpn_Tracker_Remote *tracker#; extern float xPositionDesired#; extern float yPositionDesired#; extern float zPositionDesired#; extern float yawDesired#; extern float xPosition#; extern float yPosition#; extern float zPosition#; extern CCrazyflie *cflieCopter#; extern double initTime#; extern char takeOff#; extern double takeOffTime#; void vrpn_init(std::string connectionName, void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback#)(void*, const vrpn_TRACKERCB), ......, char *key) { tracker# = new vrpn_Tracker_Remote("Crazyflie2#", connection); tracker#->register_change_handler(0, callback#); tracker#->mainloop(); </pre> </code> </blockquote> ===Changes in ''nearGround()''=== <blockquote> <code> <pre> void nearGround() //During Landing Mode checks how close to ground quad is for shutdown { ... ... ... if(cflieCopter#){ if((cflieCopter#->m_enumFlightMode == LANDING_MODE) && (zPosition# < 0.05)) { cflieCopter#->m_enumFlightMode = GROUNDED_MODE; } } } </pre> </code> </blockquote> ===Changes in ''updateHand()''=== <blockquote> <code> <pre> void updateHand() { if(handMode == 1) { // cout << "Hand Roll: " << rollHand << endl; if(killCount > 5){ ... ... cflieCopter#->m_enumFlightMode = GROUNDED_MODE; } else if(trackCount > 5){ ... ... cflieCopter#->m_enumFlightMode = HAND_MODE; } else{ ... ... if(zPositionHand > 1.6) { ... ... cflieCopter#->m_enumFlightMode = TAKEOFF_MODE; cout << "Hand Mode: Launching Quads" << endl; } else if(zPositionHand < 0.4) { ... ... cflieCopter#->m_enumFlightMode = LANDING_MODE; ... } } } } </pre> </code> </blockquote> ==Changes in ''vrpn.h''== <blockquote> <code> <pre> void vrpn_init(std::string connectionName, void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback#)(void*, const vrpn_TRACKERCB), ...., char *key); </pre> </code> </blockquote> ==Changes in ''eris_vrpn.cpp''== ===Global Variables=== <blockquote> <code> <pre> void VRPN_CALLBACK handle_Crazyflie#(void*, const vrpn_TRACKERCB t); CCrazyRadio *crRadio# = 0; //***NOT NECESSARY IF LESS THAN 3 QUADS PER RADIO*** CCrazyflie *cflieCopter# = 0; ControllerObject pidCtrl# = { 0 }; // init all fields to zero float rollControlOutput#; float pitchControlOutput#; float yawControlOutput#; float thrustControlOutput#; double initTime# = 0; int vrpnPacketBackup# = 0; double vrpnBackupTime# = 0; double vrpnBackupTime#Prev = 0; double vrpnBackupTime#Delta = 0; float xPositionDesired# = 0.681; float yPositionDesired# = 0.129; float zPositionDesired# = 0.6; float yawDesired# = -90.0; float yawDifference# = 0; float quadYaw# = 0; float prevQuadYaw# = 0; float camYawDeg# = 0; float camYawDeg#Off = 0; float quadYaw#Off = 0; float correctedYaw# = 0; float xError# = 0.0; float yError# = 0.0; float xStepPositionError# = 0.0; float yStepPositionError# = 0.0; float xPosition# = -0.012; float yPosition# = -0.008; //Default Crazyflie location setpoints float zPosition# = 0.75; char takeOff# = 0; double loopTime#Start = 0; double loopTime#End = 0; double loopTime# = 0; double loopTime#Prev = 0; double loopTime#Delta = 0; double vrpnPacketTime# = 0; double vrpnPacketTime#Prev = 0; double vrpnPacketDelta# = 0; FILE * out# = NULL; </pre> </code> </blockquote> ===Changes in ''main()''=== <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl# ); controllerInit( &pidCtrl# ); vrpn_init("192.168.0.120:3883", handle_pos, handle_Crazyflie2, handle_Crazyflie#, handle_Crazyflie(#+1), ..., &keystroke_now); cflieCopter# = new CCrazyflie(crRadio(radio dongle number), (Radio Channel)); const char * logHeader# = "#Crazyflie# Log File\n\ #Time\t\t........ if(cflieCopter#) { out# = fopen("cflie#.txt", "w"); if(out# == NULL) { printf("Could not open cflie#.log:errno %d\n", errno); exit(-1); } fprintf(out#, "%s\n", logHeader#); } crRadio#->setARDTime(2000); //Sets Wait Time between Packet Retries (**MUST BE IN INCREMENTS OF 250**) crRadio#->setARC(0); //Sets Number of times Retries Packet Send crRadio#->setPower(P_0DBM); cflieCopter#->setSendSetpoints( true ); initTime# = cflieCopter#->currentTime(); cflieCopter#->m_enumFlightMode = GROUNDED_MODE; fclose(out#); delete cflieCopter#; delete crRadio#; </pre> </code> </blockquote> ===Create a New Callback=== '''Note:''' To make it easier for this section you can: #COPY and PASTE the callback code directly after the last callback in the Swarm Client #Use FIND and REPLACE to replace all '#' signs with the Crazyflie number desired :*'''IMPORTANT:''' Be careful, some of the '#' symbols are used for the Radio Dongle number also. <blockquote> <code> <pre> void VRPN_CALLBACK handle_Crazyflie#(void*, const vrpn_TRACKERCB t) { if(vrpnPacketBackup# < 2) //If VRPN Buffer does NOT have old packets stored up, run main code { loopTime#Start = cflieCopter#->currentTime() - initTime#; loopTime#Delta = loopTime#Start - loopTime#Prev; //Calculates time difference between each loop start loopTime#Prev = loopTime#Start; vrpnPacketTime# = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnPacketDelta# = vrpnPacketTime# - vrpnPacketTime#Prev; vrpnPacketTime#Prev = vrpnPacketTime#; vrpnPacketBackup# = ceil(loopTime#Delta/vrpnPacketDelta#); //Calculates estimated # of packets built up in VRPN buffer. controllerSetAllDt(&pidCtrl#, vrpnPacketDelta#); //Variable dt for controller based on time between packets | vrpnPacketDelta2 cflieCopter1->cheat_process_packets(); //Flush out other Copter Packets crRadio(#RADIO NUM)->clearPackets(); crRadio(#RADIO NUM)->setChannel( cflieCopter#->radioChannel() ); frameCount++; // Get the euler angles q_vec_type euler; q_to_euler(euler, t.quat); xPosition# = t.pos[0]; yPosition# = t.pos[1]; //Stores X, Y, and Z Position for use in other Callbacks (external) zPosition# = -t.pos[2] + 0.05; #if USE_PRINTOUT cout << "PID Radio #" << endl << endl; #endif #if 0 //UNUSED (old way of storing camera data) //cout << "\033[2J\033[1;1H"; //Clears Terminal Window to display clean output cfliePitch = cflieCopter#->pitch(); cflieRoll = cflieCopter#->roll(); cflieYaw = cflieCopter#->yaw(); cflieThrust = cflieCopter#->thrust(); /* * Position * x t.pos[0] * y t.pos[1] * z t.pos[2] * * Orientation * yaw euler[0] Rotation * pitch euler[1] East-West movement * roll euler[2] North-South movement * Euler's range goes from -pi : +pi */ QUAD quad; quad.vrpnNow = 0; vrpn_data_t *vrpnData; vrpnData = (vrpn_data_t*) malloc(sizeof(vrpn_data_t)); vrpnData->usec = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnData->x = t.pos[0]; vrpnData->y = t.pos[1]; vrpnData->z = -t.pos[2] + 0.05; //Higher Altitude = Negative z //Added Offset for floor below camera system origin vrpnData->yaw = euler[0]; vrpnData->pitch = euler[1]; vrpnData->roll = euler[2]; xPosition# = t.pos[0]; yPosition# = t.pos[1]; zPosition# = -t.pos[2] + 0.05; cout << "xPosition of Crazyflie#: " << xPosition# << endl; quad.vrpnPrev = quad.vrpnNow; if (quad.vrpnNow == 0) { quad.vrpnPrev = 0; quad.vrpnTime0 = vrpnData->usec; quad.vrpnNow = vrpnData->usec; } else { quad.vrpnNow = vrpnData->usec - quad.vrpnTime0; } #endif //END UNUSED //==============YAW CORRECTION========================= (IMPORTANT!!!: YAW CONTROLLER INPUT IS INVERTED IN simple.cpp FILE***) camYawDeg# = -(euler[0] * 57.2958); //Converts From Radians TO Degrees quadYaw# = cflieCopter#->yaw(); if (frameCount == 50) { if (camYawDeg# < 0.0) camYawDeg#Off = camYawDeg# + 360.0; //Converts from +-180 to full 360 degree form else camYawDeg#Off = camYawDeg#; if(quadYaw# < 0.0) quadYaw#Off = quadYaw# + 360.0; else quadYaw#Off = quadYaw#; yawDifference# = quadYaw#Off - camYawDeg#Off; cout << "Yaw# Offset Taken: " << yawDifference# << endl; } correctedYaw# = camYawDeg# + yawDifference#; if(correctedYaw# > 180.0) correctedYaw# -= 360.0; else if(correctedYaw# < -180.0) correctedYaw# += 360.0; //===============END YAW CORRECTION========================= #if USE_PRINTOUT cout << "X: " << t.pos[0] << endl; cout << "Y: " << t.pos[1] << endl; cout << "Z: " << -t.pos[2] + 0.05 << endl; #endif #if USE_KEYBOARD if (cflieCopter#->m_enumFlightMode == LANDING_MODE) //Landing Mode (TODO Change to be a keystroke when implemented) { //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = xPositionDesired# - xPosition#; yError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, -0.4, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); takeOff# = 0; } else if (cflieCopter#->m_enumFlightMode == MIRROR_MODE) { //Acts as Master xPositionDesired# = -0.012; yPositionDesired# = -0.200; zPositionDesired# = 0.75; if( loopTime#Start - lastTime > 4.0 ) { toggle = !toggle; lastTime = loopTime#Start; } #if USE_PRINTOUT cout << "New xPositionDesired: " << xPositionDesired# << endl; #endif if(toggle) { xStepPositionError# = xPositionDesired# - xPosition#; yStepPositionError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xStepPositionError#, yStepPositionError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else { xStepPositionError# = (xPositionDesired# + 0.65) - xPosition#; yStepPositionError# = (yPositionDesired# + 0.65) - yPosition#; controllerSetXYError(&pidCtrl#, xStepPositionError#, yStepPositionError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired# + 0.65, yPositionDesired# + 0.65, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); //cout << "Toggled!" << endl; } } else if (cflieCopter#->m_enumFlightMode == TAKEOFF_MODE) { //correctedYaw# //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = xPositionDesired# - xPosition#; yError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else if (cflieCopter#->m_enumFlightMode == HAND_MODE) { //correctedYaw# //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = (xPositionHand - 0.5) - xPosition#; yError# = (yPositionHand + 0.5) - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else if(cflieCopter#->m_enumFlightMode == GROUNDED_MODE){ controllerResetAllPID(&pidCtrl#); rollControlOutput# = 0; pitchControlOutput# = 0; yawControlOutput# = 0; thrustControlOutput# = 0; } else{ //Emergency Case (Should never happen) controllerResetAllPID(&pidCtrl#); rollControlOutput# = 0; pitchControlOutput# = 0; yawControlOutput# = 0; thrustControlOutput# = 0; } #else controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], -t.pos[2], correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); #endif RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); #if USE_LOGGING #if USE_BASIC_LOGGING fprintf(out#, "%.6f\t\t", cflieCopter#->currentTime() - initTime# ); fprintf(out#, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter#->roll(), cflieCopter#->pitch(), quadYaw#, t.pos[0], t.pos[1], -t.pos[2], camYawDeg#, correctedYaw#, loopTimeTotal, loopTimeTotalDelta, loopTime#, loopTime#Delta, vrpnPacketDelta#, vrpnPacketTime#, vrpnPacketBackup#, cflieCopter#->radioRSSI()); // fprintf(out#, "\n"); #else fprintf(out#, "%.6f\t\t", cflieCopter#->currentTime() - initTime# ); fprintf(out#, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t%.3f\t\t%.3f\t\t%.3f", cflieCopter#->roll(), cflieCopter#->pitch(), quadYaw#, t.pos[0], t.pos[1], -t.pos[2], camYawDeg#, correctedYaw#, loopTimeTotal, loopTimeTotalDelta, loopTime#, loopTime#Delta, vrpnPacketDelta#, vrpnPacketTime#, vrpnPacketBackup#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, pitchControlOutput#, rollControlOutput#, yawControlOutput#, thrustControlOutput#, cflieCopter#->radioRSSI(), euler[0], euler[1], euler[2], cflieCopter#->motor1(), cflieCopter#->motor2(), cflieCopter#->motor3(), cflieCopter#->motor4(), cflieCopter#->gyroX(), cflieCopter#->gyroY(), cflieCopter#->gyroZ()); // fprintf(out#, "\n"); #endif #endif loopTime#End = cflieCopter#->currentTime() - initTime#; loopTime# = loopTime#End - loopTime#Start; } //End Packet Backup If check else if(vrpnPacketBackup# < 0){ //Failsafe so can't go below 0 (should never happen) | || (vrpnPacketBackup# > 20)? vrpnPacketBackup# = 0; // RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, // rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); } else if(vrpnPacketBackup# >= 2){ // cout << "VRPN Packet Backup # Detected: " << vrpnPacketBackup# << endl; vrpnPacketBackup# --; // RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, // rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); }//End Packet Backup Purge } //END CALLBACK # </pre> </code> </blockquote> ===Changes in CTRL+C Handler=== <blockquote> <code> <pre> cflieCopter#->setThrust(10000); cout << "Battery#: " << cflieCopter#->batteryLevel() << endl; cflieCopter#->cycle(); #if USE_LOGGING ... ... ... fclose(out#); #endif delete cflieCopter#; delete crRadio#; </pre> </code> </blockquote> ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 3fc528735308a83a3b5af1b6c777404234ce75b0 161 160 2016-07-28T18:04:51Z Jnoronha 3 added a note about the '#' symbol wikitext text/x-wiki Adding a Crazyflie to the Swarm is simple, but tedious. It's basically just replicating a copy of the other Crazyflie's code, but there are multiple files you will need to make changes in. The following list should help you locate all the code you need to replicate: *'''Note:''' Most of these changes will have a '#' symbol, you '''need to replace it''' with the corresponding Crazyflie number you are adding. ==Changes in ''vrpn.cpp''== <blockquote> <code> <pre> vrpn_Tracker_Remote *tracker#; extern float xPositionDesired#; extern float yPositionDesired#; extern float zPositionDesired#; extern float yawDesired#; extern float xPosition#; extern float yPosition#; extern float zPosition#; extern CCrazyflie *cflieCopter#; extern double initTime#; extern char takeOff#; extern double takeOffTime#; void vrpn_init(std::string connectionName, void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback#)(void*, const vrpn_TRACKERCB), ......, char *key) { tracker# = new vrpn_Tracker_Remote("Crazyflie2#", connection); tracker#->register_change_handler(0, callback#); tracker#->mainloop(); </pre> </code> </blockquote> ===Changes in ''nearGround()''=== <blockquote> <code> <pre> void nearGround() //During Landing Mode checks how close to ground quad is for shutdown { ... ... ... if(cflieCopter#){ if((cflieCopter#->m_enumFlightMode == LANDING_MODE) && (zPosition# < 0.05)) { cflieCopter#->m_enumFlightMode = GROUNDED_MODE; } } } </pre> </code> </blockquote> ===Changes in ''updateHand()''=== <blockquote> <code> <pre> void updateHand() { if(handMode == 1) { // cout << "Hand Roll: " << rollHand << endl; if(killCount > 5){ ... ... cflieCopter#->m_enumFlightMode = GROUNDED_MODE; } else if(trackCount > 5){ ... ... cflieCopter#->m_enumFlightMode = HAND_MODE; } else{ ... ... if(zPositionHand > 1.6) { ... ... cflieCopter#->m_enumFlightMode = TAKEOFF_MODE; cout << "Hand Mode: Launching Quads" << endl; } else if(zPositionHand < 0.4) { ... ... cflieCopter#->m_enumFlightMode = LANDING_MODE; ... } } } } </pre> </code> </blockquote> ==Changes in ''vrpn.h''== <blockquote> <code> <pre> void vrpn_init(std::string connectionName, void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback#)(void*, const vrpn_TRACKERCB), ...., char *key); </pre> </code> </blockquote> ==Changes in ''eris_vrpn.cpp''== ===Global Variables=== <blockquote> <code> <pre> void VRPN_CALLBACK handle_Crazyflie#(void*, const vrpn_TRACKERCB t); CCrazyRadio *crRadio# = 0; //***NOT NECESSARY IF LESS THAN 3 QUADS PER RADIO*** CCrazyflie *cflieCopter# = 0; ControllerObject pidCtrl# = { 0 }; // init all fields to zero float rollControlOutput#; float pitchControlOutput#; float yawControlOutput#; float thrustControlOutput#; double initTime# = 0; int vrpnPacketBackup# = 0; double vrpnBackupTime# = 0; double vrpnBackupTime#Prev = 0; double vrpnBackupTime#Delta = 0; float xPositionDesired# = 0.681; float yPositionDesired# = 0.129; float zPositionDesired# = 0.6; float yawDesired# = -90.0; float yawDifference# = 0; float quadYaw# = 0; float prevQuadYaw# = 0; float camYawDeg# = 0; float camYawDeg#Off = 0; float quadYaw#Off = 0; float correctedYaw# = 0; float xError# = 0.0; float yError# = 0.0; float xStepPositionError# = 0.0; float yStepPositionError# = 0.0; float xPosition# = -0.012; float yPosition# = -0.008; //Default Crazyflie location setpoints float zPosition# = 0.75; char takeOff# = 0; double loopTime#Start = 0; double loopTime#End = 0; double loopTime# = 0; double loopTime#Prev = 0; double loopTime#Delta = 0; double vrpnPacketTime# = 0; double vrpnPacketTime#Prev = 0; double vrpnPacketDelta# = 0; FILE * out# = NULL; </pre> </code> </blockquote> ===Changes in ''main()''=== <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl# ); controllerInit( &pidCtrl# ); vrpn_init("192.168.0.120:3883", handle_pos, handle_Crazyflie2, handle_Crazyflie#, handle_Crazyflie(#+1), ..., &keystroke_now); cflieCopter# = new CCrazyflie(crRadio(radio dongle number), (Radio Channel)); const char * logHeader# = "#Crazyflie# Log File\n\ #Time\t\t........ if(cflieCopter#) { out# = fopen("cflie#.txt", "w"); if(out# == NULL) { printf("Could not open cflie#.log:errno %d\n", errno); exit(-1); } fprintf(out#, "%s\n", logHeader#); } crRadio#->setARDTime(2000); //Sets Wait Time between Packet Retries (**MUST BE IN INCREMENTS OF 250**) crRadio#->setARC(0); //Sets Number of times Retries Packet Send crRadio#->setPower(P_0DBM); cflieCopter#->setSendSetpoints( true ); initTime# = cflieCopter#->currentTime(); cflieCopter#->m_enumFlightMode = GROUNDED_MODE; fclose(out#); delete cflieCopter#; delete crRadio#; </pre> </code> </blockquote> ===Create a New Callback=== '''Note:''' To make it easier for this section you can: #COPY and PASTE the callback code directly after the last callback in the Swarm Client #Use FIND and REPLACE to replace all '#' signs with the Crazyflie number desired :*'''IMPORTANT:''' Be careful, some of the '#' symbols are used for the Radio Dongle number also. <blockquote> <code> <pre> void VRPN_CALLBACK handle_Crazyflie#(void*, const vrpn_TRACKERCB t) { if(vrpnPacketBackup# < 2) //If VRPN Buffer does NOT have old packets stored up, run main code { loopTime#Start = cflieCopter#->currentTime() - initTime#; loopTime#Delta = loopTime#Start - loopTime#Prev; //Calculates time difference between each loop start loopTime#Prev = loopTime#Start; vrpnPacketTime# = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnPacketDelta# = vrpnPacketTime# - vrpnPacketTime#Prev; vrpnPacketTime#Prev = vrpnPacketTime#; vrpnPacketBackup# = ceil(loopTime#Delta/vrpnPacketDelta#); //Calculates estimated # of packets built up in VRPN buffer. controllerSetAllDt(&pidCtrl#, vrpnPacketDelta#); //Variable dt for controller based on time between packets | vrpnPacketDelta2 cflieCopter1->cheat_process_packets(); //Flush out other Copter Packets crRadio(#RADIO NUM)->clearPackets(); crRadio(#RADIO NUM)->setChannel( cflieCopter#->radioChannel() ); frameCount++; // Get the euler angles q_vec_type euler; q_to_euler(euler, t.quat); xPosition# = t.pos[0]; yPosition# = t.pos[1]; //Stores X, Y, and Z Position for use in other Callbacks (external) zPosition# = -t.pos[2] + 0.05; #if USE_PRINTOUT cout << "PID Radio #" << endl << endl; #endif #if 0 //UNUSED (old way of storing camera data) //cout << "\033[2J\033[1;1H"; //Clears Terminal Window to display clean output cfliePitch = cflieCopter#->pitch(); cflieRoll = cflieCopter#->roll(); cflieYaw = cflieCopter#->yaw(); cflieThrust = cflieCopter#->thrust(); /* * Position * x t.pos[0] * y t.pos[1] * z t.pos[2] * * Orientation * yaw euler[0] Rotation * pitch euler[1] East-West movement * roll euler[2] North-South movement * Euler's range goes from -pi : +pi */ QUAD quad; quad.vrpnNow = 0; vrpn_data_t *vrpnData; vrpnData = (vrpn_data_t*) malloc(sizeof(vrpn_data_t)); vrpnData->usec = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnData->x = t.pos[0]; vrpnData->y = t.pos[1]; vrpnData->z = -t.pos[2] + 0.05; //Higher Altitude = Negative z //Added Offset for floor below camera system origin vrpnData->yaw = euler[0]; vrpnData->pitch = euler[1]; vrpnData->roll = euler[2]; xPosition# = t.pos[0]; yPosition# = t.pos[1]; zPosition# = -t.pos[2] + 0.05; cout << "xPosition of Crazyflie#: " << xPosition# << endl; quad.vrpnPrev = quad.vrpnNow; if (quad.vrpnNow == 0) { quad.vrpnPrev = 0; quad.vrpnTime0 = vrpnData->usec; quad.vrpnNow = vrpnData->usec; } else { quad.vrpnNow = vrpnData->usec - quad.vrpnTime0; } #endif //END UNUSED //==============YAW CORRECTION========================= (IMPORTANT!!!: YAW CONTROLLER INPUT IS INVERTED IN simple.cpp FILE***) camYawDeg# = -(euler[0] * 57.2958); //Converts From Radians TO Degrees quadYaw# = cflieCopter#->yaw(); if (frameCount == 50) { if (camYawDeg# < 0.0) camYawDeg#Off = camYawDeg# + 360.0; //Converts from +-180 to full 360 degree form else camYawDeg#Off = camYawDeg#; if(quadYaw# < 0.0) quadYaw#Off = quadYaw# + 360.0; else quadYaw#Off = quadYaw#; yawDifference# = quadYaw#Off - camYawDeg#Off; cout << "Yaw# Offset Taken: " << yawDifference# << endl; } correctedYaw# = camYawDeg# + yawDifference#; if(correctedYaw# > 180.0) correctedYaw# -= 360.0; else if(correctedYaw# < -180.0) correctedYaw# += 360.0; //===============END YAW CORRECTION========================= #if USE_PRINTOUT cout << "X: " << t.pos[0] << endl; cout << "Y: " << t.pos[1] << endl; cout << "Z: " << -t.pos[2] + 0.05 << endl; #endif #if USE_KEYBOARD if (cflieCopter#->m_enumFlightMode == LANDING_MODE) //Landing Mode (TODO Change to be a keystroke when implemented) { //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = xPositionDesired# - xPosition#; yError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, -0.4, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); takeOff# = 0; } else if (cflieCopter#->m_enumFlightMode == MIRROR_MODE) { //Acts as Master xPositionDesired# = -0.012; yPositionDesired# = -0.200; zPositionDesired# = 0.75; if( loopTime#Start - lastTime > 4.0 ) { toggle = !toggle; lastTime = loopTime#Start; } #if USE_PRINTOUT cout << "New xPositionDesired: " << xPositionDesired# << endl; #endif if(toggle) { xStepPositionError# = xPositionDesired# - xPosition#; yStepPositionError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xStepPositionError#, yStepPositionError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else { xStepPositionError# = (xPositionDesired# + 0.65) - xPosition#; yStepPositionError# = (yPositionDesired# + 0.65) - yPosition#; controllerSetXYError(&pidCtrl#, xStepPositionError#, yStepPositionError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired# + 0.65, yPositionDesired# + 0.65, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); //cout << "Toggled!" << endl; } } else if (cflieCopter#->m_enumFlightMode == TAKEOFF_MODE) { //correctedYaw# //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = xPositionDesired# - xPosition#; yError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else if (cflieCopter#->m_enumFlightMode == HAND_MODE) { //correctedYaw# //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = (xPositionHand - 0.5) - xPosition#; yError# = (yPositionHand + 0.5) - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else if(cflieCopter#->m_enumFlightMode == GROUNDED_MODE){ controllerResetAllPID(&pidCtrl#); rollControlOutput# = 0; pitchControlOutput# = 0; yawControlOutput# = 0; thrustControlOutput# = 0; } else{ //Emergency Case (Should never happen) controllerResetAllPID(&pidCtrl#); rollControlOutput# = 0; pitchControlOutput# = 0; yawControlOutput# = 0; thrustControlOutput# = 0; } #else controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], -t.pos[2], correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); #endif RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); #if USE_LOGGING #if USE_BASIC_LOGGING fprintf(out#, "%.6f\t\t", cflieCopter#->currentTime() - initTime# ); fprintf(out#, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter#->roll(), cflieCopter#->pitch(), quadYaw#, t.pos[0], t.pos[1], -t.pos[2], camYawDeg#, correctedYaw#, loopTimeTotal, loopTimeTotalDelta, loopTime#, loopTime#Delta, vrpnPacketDelta#, vrpnPacketTime#, vrpnPacketBackup#, cflieCopter#->radioRSSI()); // fprintf(out#, "\n"); #else fprintf(out#, "%.6f\t\t", cflieCopter#->currentTime() - initTime# ); fprintf(out#, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t%.3f\t\t%.3f\t\t%.3f", cflieCopter#->roll(), cflieCopter#->pitch(), quadYaw#, t.pos[0], t.pos[1], -t.pos[2], camYawDeg#, correctedYaw#, loopTimeTotal, loopTimeTotalDelta, loopTime#, loopTime#Delta, vrpnPacketDelta#, vrpnPacketTime#, vrpnPacketBackup#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, pitchControlOutput#, rollControlOutput#, yawControlOutput#, thrustControlOutput#, cflieCopter#->radioRSSI(), euler[0], euler[1], euler[2], cflieCopter#->motor1(), cflieCopter#->motor2(), cflieCopter#->motor3(), cflieCopter#->motor4(), cflieCopter#->gyroX(), cflieCopter#->gyroY(), cflieCopter#->gyroZ()); // fprintf(out#, "\n"); #endif #endif loopTime#End = cflieCopter#->currentTime() - initTime#; loopTime# = loopTime#End - loopTime#Start; } //End Packet Backup If check else if(vrpnPacketBackup# < 0){ //Failsafe so can't go below 0 (should never happen) | || (vrpnPacketBackup# > 20)? vrpnPacketBackup# = 0; // RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, // rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); } else if(vrpnPacketBackup# >= 2){ // cout << "VRPN Packet Backup # Detected: " << vrpnPacketBackup# << endl; vrpnPacketBackup# --; // RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, // rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); }//End Packet Backup Purge } //END CALLBACK # </pre> </code> </blockquote> ===Changes in CTRL+C Handler=== <blockquote> <code> <pre> cflieCopter#->setThrust(10000); cout << "Battery#: " << cflieCopter#->batteryLevel() << endl; cflieCopter#->cycle(); #if USE_LOGGING ... ... ... fclose(out#); #endif delete cflieCopter#; delete crRadio#; </pre> </code> </blockquote> ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> e2f05b96aff0320be04dce91aedf0af5c68175f0 162 161 2016-07-28T18:05:09Z Jnoronha 3 bolded more wikitext text/x-wiki Adding a Crazyflie to the Swarm is simple, but tedious. It's basically just replicating a copy of the other Crazyflie's code, but there are multiple files you will need to make changes in. The following list should help you locate all the code you need to replicate: *'''Note:''' Most of these changes will have a '#' symbol, you '''need to replace it with the corresponding Crazyflie number''' you are adding. ==Changes in ''vrpn.cpp''== <blockquote> <code> <pre> vrpn_Tracker_Remote *tracker#; extern float xPositionDesired#; extern float yPositionDesired#; extern float zPositionDesired#; extern float yawDesired#; extern float xPosition#; extern float yPosition#; extern float zPosition#; extern CCrazyflie *cflieCopter#; extern double initTime#; extern char takeOff#; extern double takeOffTime#; void vrpn_init(std::string connectionName, void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback#)(void*, const vrpn_TRACKERCB), ......, char *key) { tracker# = new vrpn_Tracker_Remote("Crazyflie2#", connection); tracker#->register_change_handler(0, callback#); tracker#->mainloop(); </pre> </code> </blockquote> ===Changes in ''nearGround()''=== <blockquote> <code> <pre> void nearGround() //During Landing Mode checks how close to ground quad is for shutdown { ... ... ... if(cflieCopter#){ if((cflieCopter#->m_enumFlightMode == LANDING_MODE) && (zPosition# < 0.05)) { cflieCopter#->m_enumFlightMode = GROUNDED_MODE; } } } </pre> </code> </blockquote> ===Changes in ''updateHand()''=== <blockquote> <code> <pre> void updateHand() { if(handMode == 1) { // cout << "Hand Roll: " << rollHand << endl; if(killCount > 5){ ... ... cflieCopter#->m_enumFlightMode = GROUNDED_MODE; } else if(trackCount > 5){ ... ... cflieCopter#->m_enumFlightMode = HAND_MODE; } else{ ... ... if(zPositionHand > 1.6) { ... ... cflieCopter#->m_enumFlightMode = TAKEOFF_MODE; cout << "Hand Mode: Launching Quads" << endl; } else if(zPositionHand < 0.4) { ... ... cflieCopter#->m_enumFlightMode = LANDING_MODE; ... } } } } </pre> </code> </blockquote> ==Changes in ''vrpn.h''== <blockquote> <code> <pre> void vrpn_init(std::string connectionName, void (*callback)(void*, const vrpn_TRACKERCB), void (*callback2)(void*, const vrpn_TRACKERCB), void (*callback#)(void*, const vrpn_TRACKERCB), ...., char *key); </pre> </code> </blockquote> ==Changes in ''eris_vrpn.cpp''== ===Global Variables=== <blockquote> <code> <pre> void VRPN_CALLBACK handle_Crazyflie#(void*, const vrpn_TRACKERCB t); CCrazyRadio *crRadio# = 0; //***NOT NECESSARY IF LESS THAN 3 QUADS PER RADIO*** CCrazyflie *cflieCopter# = 0; ControllerObject pidCtrl# = { 0 }; // init all fields to zero float rollControlOutput#; float pitchControlOutput#; float yawControlOutput#; float thrustControlOutput#; double initTime# = 0; int vrpnPacketBackup# = 0; double vrpnBackupTime# = 0; double vrpnBackupTime#Prev = 0; double vrpnBackupTime#Delta = 0; float xPositionDesired# = 0.681; float yPositionDesired# = 0.129; float zPositionDesired# = 0.6; float yawDesired# = -90.0; float yawDifference# = 0; float quadYaw# = 0; float prevQuadYaw# = 0; float camYawDeg# = 0; float camYawDeg#Off = 0; float quadYaw#Off = 0; float correctedYaw# = 0; float xError# = 0.0; float yError# = 0.0; float xStepPositionError# = 0.0; float yStepPositionError# = 0.0; float xPosition# = -0.012; float yPosition# = -0.008; //Default Crazyflie location setpoints float zPosition# = 0.75; char takeOff# = 0; double loopTime#Start = 0; double loopTime#End = 0; double loopTime# = 0; double loopTime#Prev = 0; double loopTime#Delta = 0; double vrpnPacketTime# = 0; double vrpnPacketTime#Prev = 0; double vrpnPacketDelta# = 0; FILE * out# = NULL; </pre> </code> </blockquote> ===Changes in ''main()''=== <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl# ); controllerInit( &pidCtrl# ); vrpn_init("192.168.0.120:3883", handle_pos, handle_Crazyflie2, handle_Crazyflie#, handle_Crazyflie(#+1), ..., &keystroke_now); cflieCopter# = new CCrazyflie(crRadio(radio dongle number), (Radio Channel)); const char * logHeader# = "#Crazyflie# Log File\n\ #Time\t\t........ if(cflieCopter#) { out# = fopen("cflie#.txt", "w"); if(out# == NULL) { printf("Could not open cflie#.log:errno %d\n", errno); exit(-1); } fprintf(out#, "%s\n", logHeader#); } crRadio#->setARDTime(2000); //Sets Wait Time between Packet Retries (**MUST BE IN INCREMENTS OF 250**) crRadio#->setARC(0); //Sets Number of times Retries Packet Send crRadio#->setPower(P_0DBM); cflieCopter#->setSendSetpoints( true ); initTime# = cflieCopter#->currentTime(); cflieCopter#->m_enumFlightMode = GROUNDED_MODE; fclose(out#); delete cflieCopter#; delete crRadio#; </pre> </code> </blockquote> ===Create a New Callback=== '''Note:''' To make it easier for this section you can: #COPY and PASTE the callback code directly after the last callback in the Swarm Client #Use FIND and REPLACE to replace all '#' signs with the Crazyflie number desired :*'''IMPORTANT:''' Be careful, some of the '#' symbols are used for the Radio Dongle number also. <blockquote> <code> <pre> void VRPN_CALLBACK handle_Crazyflie#(void*, const vrpn_TRACKERCB t) { if(vrpnPacketBackup# < 2) //If VRPN Buffer does NOT have old packets stored up, run main code { loopTime#Start = cflieCopter#->currentTime() - initTime#; loopTime#Delta = loopTime#Start - loopTime#Prev; //Calculates time difference between each loop start loopTime#Prev = loopTime#Start; vrpnPacketTime# = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnPacketDelta# = vrpnPacketTime# - vrpnPacketTime#Prev; vrpnPacketTime#Prev = vrpnPacketTime#; vrpnPacketBackup# = ceil(loopTime#Delta/vrpnPacketDelta#); //Calculates estimated # of packets built up in VRPN buffer. controllerSetAllDt(&pidCtrl#, vrpnPacketDelta#); //Variable dt for controller based on time between packets | vrpnPacketDelta2 cflieCopter1->cheat_process_packets(); //Flush out other Copter Packets crRadio(#RADIO NUM)->clearPackets(); crRadio(#RADIO NUM)->setChannel( cflieCopter#->radioChannel() ); frameCount++; // Get the euler angles q_vec_type euler; q_to_euler(euler, t.quat); xPosition# = t.pos[0]; yPosition# = t.pos[1]; //Stores X, Y, and Z Position for use in other Callbacks (external) zPosition# = -t.pos[2] + 0.05; #if USE_PRINTOUT cout << "PID Radio #" << endl << endl; #endif #if 0 //UNUSED (old way of storing camera data) //cout << "\033[2J\033[1;1H"; //Clears Terminal Window to display clean output cfliePitch = cflieCopter#->pitch(); cflieRoll = cflieCopter#->roll(); cflieYaw = cflieCopter#->yaw(); cflieThrust = cflieCopter#->thrust(); /* * Position * x t.pos[0] * y t.pos[1] * z t.pos[2] * * Orientation * yaw euler[0] Rotation * pitch euler[1] East-West movement * roll euler[2] North-South movement * Euler's range goes from -pi : +pi */ QUAD quad; quad.vrpnNow = 0; vrpn_data_t *vrpnData; vrpnData = (vrpn_data_t*) malloc(sizeof(vrpn_data_t)); vrpnData->usec = t.msg_time.tv_sec + (t.msg_time.tv_usec / 1000000.0); vrpnData->x = t.pos[0]; vrpnData->y = t.pos[1]; vrpnData->z = -t.pos[2] + 0.05; //Higher Altitude = Negative z //Added Offset for floor below camera system origin vrpnData->yaw = euler[0]; vrpnData->pitch = euler[1]; vrpnData->roll = euler[2]; xPosition# = t.pos[0]; yPosition# = t.pos[1]; zPosition# = -t.pos[2] + 0.05; cout << "xPosition of Crazyflie#: " << xPosition# << endl; quad.vrpnPrev = quad.vrpnNow; if (quad.vrpnNow == 0) { quad.vrpnPrev = 0; quad.vrpnTime0 = vrpnData->usec; quad.vrpnNow = vrpnData->usec; } else { quad.vrpnNow = vrpnData->usec - quad.vrpnTime0; } #endif //END UNUSED //==============YAW CORRECTION========================= (IMPORTANT!!!: YAW CONTROLLER INPUT IS INVERTED IN simple.cpp FILE***) camYawDeg# = -(euler[0] * 57.2958); //Converts From Radians TO Degrees quadYaw# = cflieCopter#->yaw(); if (frameCount == 50) { if (camYawDeg# < 0.0) camYawDeg#Off = camYawDeg# + 360.0; //Converts from +-180 to full 360 degree form else camYawDeg#Off = camYawDeg#; if(quadYaw# < 0.0) quadYaw#Off = quadYaw# + 360.0; else quadYaw#Off = quadYaw#; yawDifference# = quadYaw#Off - camYawDeg#Off; cout << "Yaw# Offset Taken: " << yawDifference# << endl; } correctedYaw# = camYawDeg# + yawDifference#; if(correctedYaw# > 180.0) correctedYaw# -= 360.0; else if(correctedYaw# < -180.0) correctedYaw# += 360.0; //===============END YAW CORRECTION========================= #if USE_PRINTOUT cout << "X: " << t.pos[0] << endl; cout << "Y: " << t.pos[1] << endl; cout << "Z: " << -t.pos[2] + 0.05 << endl; #endif #if USE_KEYBOARD if (cflieCopter#->m_enumFlightMode == LANDING_MODE) //Landing Mode (TODO Change to be a keystroke when implemented) { //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = xPositionDesired# - xPosition#; yError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, -0.4, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); takeOff# = 0; } else if (cflieCopter#->m_enumFlightMode == MIRROR_MODE) { //Acts as Master xPositionDesired# = -0.012; yPositionDesired# = -0.200; zPositionDesired# = 0.75; if( loopTime#Start - lastTime > 4.0 ) { toggle = !toggle; lastTime = loopTime#Start; } #if USE_PRINTOUT cout << "New xPositionDesired: " << xPositionDesired# << endl; #endif if(toggle) { xStepPositionError# = xPositionDesired# - xPosition#; yStepPositionError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xStepPositionError#, yStepPositionError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else { xStepPositionError# = (xPositionDesired# + 0.65) - xPosition#; yStepPositionError# = (yPositionDesired# + 0.65) - yPosition#; controllerSetXYError(&pidCtrl#, xStepPositionError#, yStepPositionError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired# + 0.65, yPositionDesired# + 0.65, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); //cout << "Toggled!" << endl; } } else if (cflieCopter#->m_enumFlightMode == TAKEOFF_MODE) { //correctedYaw# //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = xPositionDesired# - xPosition#; yError# = yPositionDesired# - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else if (cflieCopter#->m_enumFlightMode == HAND_MODE) { //correctedYaw# //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION // xError# = cos(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) - sin(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); // yError# = sin(correctedYaw# / 57.2958)*(xPositionDesired# - xPosition#) + cos(correctedYaw# / 57.2958)*(yPositionDesired# - yPosition#); xError# = (xPositionHand - 0.5) - xPosition#; yError# = (yPositionHand + 0.5) - yPosition#; controllerSetXYError(&pidCtrl#, xError#, yError#); controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], zPosition#, correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); } else if(cflieCopter#->m_enumFlightMode == GROUNDED_MODE){ controllerResetAllPID(&pidCtrl#); rollControlOutput# = 0; pitchControlOutput# = 0; yawControlOutput# = 0; thrustControlOutput# = 0; } else{ //Emergency Case (Should never happen) controllerResetAllPID(&pidCtrl#); rollControlOutput# = 0; pitchControlOutput# = 0; yawControlOutput# = 0; thrustControlOutput# = 0; } #else controllerCorrectAttitudePID(&pidCtrl#, t.pos[0], t.pos[1], -t.pos[2], correctedYaw#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, &rollControlOutput#, &pitchControlOutput#, &yawControlOutput#, &thrustControlOutput#); #endif RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); #if USE_LOGGING #if USE_BASIC_LOGGING fprintf(out#, "%.6f\t\t", cflieCopter#->currentTime() - initTime# ); fprintf(out#, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter#->roll(), cflieCopter#->pitch(), quadYaw#, t.pos[0], t.pos[1], -t.pos[2], camYawDeg#, correctedYaw#, loopTimeTotal, loopTimeTotalDelta, loopTime#, loopTime#Delta, vrpnPacketDelta#, vrpnPacketTime#, vrpnPacketBackup#, cflieCopter#->radioRSSI()); // fprintf(out#, "\n"); #else fprintf(out#, "%.6f\t\t", cflieCopter#->currentTime() - initTime# ); fprintf(out#, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%d\t\t%.3f\t\t%.3f\t\t%.3f\t\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t%.3f\t\t%.3f\t\t%.3f", cflieCopter#->roll(), cflieCopter#->pitch(), quadYaw#, t.pos[0], t.pos[1], -t.pos[2], camYawDeg#, correctedYaw#, loopTimeTotal, loopTimeTotalDelta, loopTime#, loopTime#Delta, vrpnPacketDelta#, vrpnPacketTime#, vrpnPacketBackup#, xPositionDesired#, yPositionDesired#, zPositionDesired#, yawDesired#, pitchControlOutput#, rollControlOutput#, yawControlOutput#, thrustControlOutput#, cflieCopter#->radioRSSI(), euler[0], euler[1], euler[2], cflieCopter#->motor1(), cflieCopter#->motor2(), cflieCopter#->motor3(), cflieCopter#->motor4(), cflieCopter#->gyroX(), cflieCopter#->gyroY(), cflieCopter#->gyroZ()); // fprintf(out#, "\n"); #endif #endif loopTime#End = cflieCopter#->currentTime() - initTime#; loopTime# = loopTime#End - loopTime#Start; } //End Packet Backup If check else if(vrpnPacketBackup# < 0){ //Failsafe so can't go below 0 (should never happen) | || (vrpnPacketBackup# > 20)? vrpnPacketBackup# = 0; // RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, // rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); } else if(vrpnPacketBackup# >= 2){ // cout << "VRPN Packet Backup # Detected: " << vrpnPacketBackup# << endl; vrpnPacketBackup# --; // RunCrazyflie(crRadio(#RADIO NUM), cflieCopter#, // rollControlOutput#, pitchControlOutput#, yawControlOutput#, thrustControlOutput#); }//End Packet Backup Purge } //END CALLBACK # </pre> </code> </blockquote> ===Changes in CTRL+C Handler=== <blockquote> <code> <pre> cflieCopter#->setThrust(10000); cout << "Battery#: " << cflieCopter#->batteryLevel() << endl; cflieCopter#->cycle(); #if USE_LOGGING ... ... ... fclose(out#); #endif delete cflieCopter#; delete crRadio#; </pre> </code> </blockquote> ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 58ae3b3c28a725bc7465b379de4d526adc856264 PC Client Software 0 25 163 134 2016-07-28T18:24:14Z Jnoronha 3 /* Makefile */ added the makefile code wikitext text/x-wiki The PC Client software comes in many forms. The out-of-the-box Client is written in Python and has a Graphical User Interface (GUI). The GUI is well suited for beginners, but can only support a single Radio and a single Crazyflie at a time. The easiest way to start out is with the [https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze Virtual Machine (VM)], which comes with all the files and dependencies pre-installed and can run on any computer (Windows, Mac, Linux, etc.). For more advanced users who want to use the swarm capabilities of our platform will have to use the [[#Swarm Client|Swarm Client]] we developed in C and C++. ==[https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze VM]== ('''Note:''' The VM is updated frequently so the information below may be different than the current VM) The Bitcraze wiki has a tutorial on [https://wiki.bitcraze.io/projects:virtualmachine:tutorials:vmware-win7 installing the VM]. Along with another tutorial on how to get started [https://www.bitcraze.io/getting-started-with-development/ using the VM]. These are both very simple starting guides that will help you become familiar with the VM. ===Crazyflie Client GUI=== On the VM you can find the Crazyflie Client Graphical User Interface (GUI). To run the Client you want to open a terminal and navigate to <code>projects/''''FIND PATH''''</code> and then run the command <code>sudo ./bin/cfclient</code> (Alternatively, you can use the desktop to navigate to the folder and open a terminal there) Once you do that you should see something similar to this: [[Image:DefaultCrazyflieGUIMainScreen.JPG|500px]] This is the main screen of the Client GUI and there are many tabs and features that you can access directly from this screen. The most important parts of this screen are the following: #Connect Button #Bootloader (Crazyflie Drop Down -> Bootloader) #Plotter Tab #Log Blocks Tab #Parameters Tab ====Connect Button==== This is where you will scan for Crazyflies that are powered ON. All Crazyflies not already connected will show up in the popup [[Image:DefaultCrazyflieGUIConnectScreen.JPG|400px]] We get a return that says <code>radio://0/45/2M</code>, this line is the identifier string of the Crazyflie we are trying to connect to. What this is saying is that we got a return from a Radio (Radio 0 specifically), from a Crazyflie on Channel 45 using a data rate of 2Mbps. ====Bootloader==== This where you can install new Firmware to the Crazyflie. [[Image:DefaultCrazyflieGUIBootloader.JPG|500px]] The first thing you'll need to update is to build the Firmware version you want into a .bin file. You can do this by just running the <code>make</code> command in terminal while located inside the Firmware directory you have modified. Once you have that .bin file built you: #Open the bootloader shown #Hold down the power button on the Crazyflie 2.0 for around 3 seconds until the 2 blue LED's flash and alternate. This puts the Crazyflie in bootloader mode. ('''NOTE:''' Recommend having '''ALL other Crazyflies OFF''' or else it could accidentally flash both Crazyflies.) #Then hit ''Initiate bootloader cold boot'' (it should connect to the Crazyflie in bootloader mode after a few seconds, Status will change from 'Not Connected' to 'Connected') #Hit ''Browse'' and find the .bin file you built earlier. #Then click ''Program'' and wait for the progress bar to complete. #Restart the Crazyflie in Firmware mode and make sure it starts up normally, if something seems wrong just repeat steps 2 through 6 again. ====Logging Tab==== Once you connect to a Crazyflie you can monitor certain log variables that have been set up. You will see a plot of the data similar to this: [[Image:DefaultCrazyflieGUILoggerScreen.JPG|400px]] On this screen we can do the following things: *Dropdown Menu at the top of the screen **Select which log block you want to plot on screen. *Scale the X-axis of the plot by: **Range **Number of Samples **Time in Seconds **Manually *Scale the Y-axis by: **Automatically **Manual Range ====Parameters Tab==== This tab displays all the parameters currently set up on the Crazyflie Firmware. Once you connect to a Crazyflie it lists these parameters in a table format similar to below: [[Image:DefaultCrazyflieGUIParametersScreen.JPG|400px]] For each parameter we get its Name, Variable Type, Access Type (Read/Write), and its Current Value. We can also modify the parameter values on this screen in real-time and the changes will be sent to the Crazyflie automatically. ('''Note:''' Any parameter changes made on this screen are NOT preserved when you turn OFF the Crazyflie.) ==Swarm Client== The swarm Client is a re-creation of the Original Client but programmed in C and C++. The benefit of this is that *We use a unified language between Client and Firmware *Easily migrate this platform to any linux distribution that can install the Crazyflie dependencies. **Our platform code itself requires only the VRPN libraries and a generic C compiler. ===Using the Swarm Client=== The Swarm Client uses the terminal interface for User Input. [[Image:CrazyflieTerminalInitial.png|400px]] Here we see what the initial Terminal looks like before we do anything. :1. The first thing you want to do before any testing is to run the <code>sudo make</code> command in the Swarm Client directory. (Yes, the 'sudo' is necessary) ::This will make sure you have all the necessary dependencies, that the code is error free, and then it will build an executable (.exe) file of the Swarm Client code. An error free make will look something like this: ::[[Image:CrazyflieTerminalPostMake.png|400px]] ::There will be warnings, but those don't cause any issues right now. :2. Pre-Test Checklist ::*Camera System is Turned on and Crazyflie Trackables are opened and visible. ::*Radios are plugged into the USB Ports on the Client computer. ::*Crazyflies are ON and NOT in an Error State. :3. Run the executable file using the command <code>sudo ./eris_vrpn</code> in the same directory (Yes, the 'sudo' is necessary). This will start the program initialization and a bunch of status info will flood the screen. You will know the program is ready for input when you see the following: ::[[Image:CrazyflieTerminalProgramStarted.png|400px]] ::This means that the Crazyflie yaw has been synchronized with the Camera system and they are ready to fly. :4. Input a Keyboard Command ::This will depend on what you have programmed as the keyboard input commands. As of 7/19/16 we have the following Keyboard Commands active: ::*'1' - Rotates Yaw of Crazyflie1 +45 degrees ::*'2' - Rotates Yaw of Crazyflie1 -45 degrees ::*'q' - Ends Main Loop (OBSOLETE - Replaced with ctrl + c) ::*'e' - Landing Mode (for ALL Crazyflies) ::*'t' - Crazyflie1 Take-Off ::*'y' - Crazyflie2 Take-Off ::*'u' - Crazyflie3 Take-Off ::*'i' - Crazyflie4 Take-Off ::*'h' - Hand Gesture Mode (for ALL Crazyflies) ::*'m' - Mirror Mode (for ALL Crazyflies) ::*ctrl+c - Quits Program, performs all cleanup. ::An example of what this would look like in the Terminal is shown here: ::[[Image:CrazyflieTerminalKeyboardInput.png|400px]] ::So you can see we commanded all 4 Crazyflies to take off (t,y,u,i), then activated Landing Mode (e), then activated Hand Mode (h), and then Ended the Program (ctrl+c). :5. End Program when finished (ctrl+c) ::This will end the program loop, print the current battery levels, and Delete the Radio pointers (shown at the end of the previous figure) ===Makefile=== The Swarm Client is compiled by a simple makefile. So when you call ''sudo make'' this makefile converts the C++ code files into an executable (.exe) for us. <blockquote> <code> <pre> g++ = g++ -Wall all: eris_vrpn eris_vrpn: eris_vrpn.h eris_vrpn.cpp vrpn.h vrpn.cpp CCrazyflie.h CCrazyflie.cpp CCrazyRadio.h CCrazyRadio.cpp CCRTPPacket.h CCRTPPacket.cpp CTOC.h CTOC.cpp simple.cpp simple.h pid.h pid.c controller.h controller.c multicast.c $(g++) -g -O0 -o eris_vrpn eris_vrpn.cpp vrpn.cpp CCrazyflie.cpp CCrazyRadio.cpp CCRTPPacket.cpp CTOC.cpp simple.cpp pid.c controller.c multicast.c -lquat -lvrpn -lpthread -lusb-1.0 clean: rm -f *.o eris_vrpn </pre> </code> </blockquote> ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 4f0c282502b293018efc0e3e4e78f41e84d3cfc2 Future Project Ideas 0 47 164 2016-07-28T18:55:42Z Jnoronha 3 added PID to firmware details wikitext text/x-wiki Here we will go into more depth on what each of these projects would require: ==Migrating Swarm Client PID's to Firmware== ===Focus Area=== *Firmware Programming and Communication Protocols **This project requires heavy modification of the Firmware and Communication systems inside the Crazyflie. ===Tasks=== ====Firmware==== *'''(HARD)''' Modifying [https://wiki.bitcraze.io/projects:crazyflie:crtp:commander Commander Packet Structure] to allow position data to be sent rather than pitch, roll, yaw, and thrust setpoints. *Modifying Firmware to pass the new position data into the correct place for use by the Firmware PID controllers. ====Client==== *Modify Swarm Client packet construction to match new commander packet protocol in Firmware *'''(EASY)''' Remove Controllers from callbacks and just send location packets to Crazyflies while still maintaining other functionality. ===Benefits=== *Significantly reduces Client-side computation and allows Crazyflie swarm to share the load. *Potential extension to completely independent Crazyflie flight (i.e. No Client needed at all) ==Tuning X, Y, and Z Location PID's for Faster Response== ==Adding Parameter Support to Swarm Client== ==Threading Each USB Radio to speed up Computation== ==Crazyflie Model Development and Verification== ==Developing New Controllers for the Crazyflie (pending Model Development)== ==Develop Communications Network Between Crazyflies== ==Trilateration Position Estimation using a Swarm== ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> fc38c9df27be9233714d5e1d1d6d7ec468b48bc8 166 164 2016-07-28T19:08:41Z Jnoronha 3 /* Tuning X, Y, and Z Location PID's for Faster Response */ finished section wikitext text/x-wiki Here we will go into more depth on what each of these projects would require: ==Migrating Swarm Client PID's to Firmware== ===Focus Area=== *Firmware Programming and Communication Protocols **This project requires heavy modification of the Firmware and Communication systems inside the Crazyflie. ===Tasks=== ====Firmware==== *'''(HARD)''' Modifying [https://wiki.bitcraze.io/projects:crazyflie:crtp:commander Commander Packet Structure] to allow position data to be sent rather than pitch, roll, yaw, and thrust setpoints. *Modifying Firmware to pass the new position data into the correct place for use by the Firmware PID controllers. ====Client==== *Modify Swarm Client packet construction to match new commander packet protocol in Firmware *'''(EASY)''' Remove Controllers from callbacks and just send location packets to Crazyflies while still maintaining other functionality. ===Benefits=== *Significantly reduces Client-side computation and allows Crazyflie swarm to share the load. *Potential extension to completely independent Crazyflie flight (i.e. No Client needed at all) ==Tuning X, Y, and Z Location PID's for Faster Response== ===Focus Area=== '''Control Systems and Model Development/Verification''' *This project will require developing a model of the Crazyflie system and using the Model to calculate PID constants. ===Tasks=== *'''(HARD)''' Identify model Parameters for the Crazyflie *Construct model in Simulink and Verify simulation compared to test data *'''(EASY)''' Derive PID constants from verified model, test flight performance ===Benefits=== *'''VERIFIED MODEL!!''' We can do many things once we have a verified model of the system. *Flight performance will be greatly improved allowing more complex applications to be developed. *'''Potential extension:''' Path prediction algorithms and optimal pathing between points with obstacles ==Adding Parameter Support to Swarm Client== ==Threading Each USB Radio to speed up Computation== ==Crazyflie Model Development and Verification== ==Developing New Controllers for the Crazyflie (pending Model Development)== ==Develop Communications Network Between Crazyflies== ==Trilateration Position Estimation using a Swarm== ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> a6d836255f0cdb40bdc11d406d726f4ffed46a6a 167 166 2016-07-28T19:09:26Z Jnoronha 3 /* Migrating Swarm Client PID's to Firmware */ formatting wikitext text/x-wiki Here we will go into more depth on what each of these projects would require: ==Migrating Swarm Client PID's to Firmware== ===Focus Area=== '''Firmware Programming and Communication Protocols''' *This project requires heavy modification of the Firmware and Communication systems inside the Crazyflie. ===Tasks=== ====Firmware==== *'''(HARD)''' Modifying [https://wiki.bitcraze.io/projects:crazyflie:crtp:commander Commander Packet Structure] to allow position data to be sent rather than pitch, roll, yaw, and thrust setpoints. *Modifying Firmware to pass the new position data into the correct place for use by the Firmware PID controllers. ====Client==== *Modify Swarm Client packet construction to match new commander packet protocol in Firmware *'''(EASY)''' Remove Controllers from callbacks and just send location packets to Crazyflies while still maintaining other functionality. ===Benefits=== *Significantly reduces Client-side computation and allows Crazyflie swarm to share the load. *'''Potential extension:''' Completely independent Crazyflie flight (i.e. No Client needed at all) ==Tuning X, Y, and Z Location PID's for Faster Response== ===Focus Area=== '''Control Systems and Model Development/Verification''' *This project will require developing a model of the Crazyflie system and using the Model to calculate PID constants. ===Tasks=== *'''(HARD)''' Identify model Parameters for the Crazyflie *Construct model in Simulink and Verify simulation compared to test data *'''(EASY)''' Derive PID constants from verified model, test flight performance ===Benefits=== *'''VERIFIED MODEL!!''' We can do many things once we have a verified model of the system. *Flight performance will be greatly improved allowing more complex applications to be developed. *'''Potential extension:''' Path prediction algorithms and optimal pathing between points with obstacles ==Adding Parameter Support to Swarm Client== ==Threading Each USB Radio to speed up Computation== ==Crazyflie Model Development and Verification== ==Developing New Controllers for the Crazyflie (pending Model Development)== ==Develop Communications Network Between Crazyflies== ==Trilateration Position Estimation using a Swarm== ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 93ba24762e147af05bf44a9e3932dca78dccec24 173 167 2016-07-28T19:25:59Z Jnoronha 3 /* Adding Parameter Support to Swarm Client */ finished section wikitext text/x-wiki Here we will go into more depth on what each of these projects would require: ==Migrating Swarm Client PID's to Firmware== ===Focus Area=== '''Firmware Programming and Communication Protocols''' *This project requires heavy modification of the Firmware and Communication systems inside the Crazyflie. ===Tasks=== ====Firmware==== *'''(HARD)''' Modifying [https://wiki.bitcraze.io/projects:crazyflie:crtp:commander Commander Packet Structure] to allow position data to be sent rather than pitch, roll, yaw, and thrust setpoints. *Modifying Firmware to pass the new position data into the correct place for use by the Firmware PID controllers. ====Client==== *Modify Swarm Client packet construction to match new commander packet protocol in Firmware *'''(EASY)''' Remove Controllers from callbacks and just send location packets to Crazyflies while still maintaining other functionality. ===Benefits=== *Significantly reduces Client-side computation and allows Crazyflie swarm to share the load. *'''Potential extension:''' Completely independent Crazyflie flight (i.e. No Client needed at all) ==Tuning X, Y, and Z Location PID's for Faster Response== ===Focus Area=== '''Control Systems and Model Development/Verification''' *This project will require developing a model of the Crazyflie system and using the Model to calculate PID constants. ===Tasks=== *'''(HARD)''' Identify model Parameters for the Crazyflie *Construct model in Simulink and Verify simulation compared to test data *'''(EASY)''' Derive PID constants from verified model, test flight performance ===Benefits=== *'''VERIFIED MODEL!!''' We can do many things once we have a verified model of the system. *Flight performance will be greatly improved allowing more complex applications to be developed. *'''Potential extension:''' Path prediction algorithms and optimal pathing between points with obstacles ==Adding Parameter Support to Swarm Client== ===Focus Area=== '''Communications Protocols and Networking''' *This project will require Client-side software development to create helper functions for easy modification of parameters on the Crazyflie Firmware ===Tasks=== *Creating packet framework in the Client to replicate the [https://wiki.bitcraze.io/projects:crazyflie:firmware:comm_protocol#parameters parameters packet protocol] *Programming helper functions to make it simple to modify parameters **Ex. Write Parameter Value: <code>setParam(string "param_group.param_name", int set_value);</code> **Ex. Read Parameter Value: <code>readParam(string "param_group.param_name");</code> ===Benefits=== *Won't have to re-flash Firmware every time we want to test a parameter change (Improves Firmware testing efficiency) *Less Firmware modification if we can just write params during Client init. *'''Potential Extension:''' Tuning Firmware PID constants ==Threading Each USB Radio to speed up Computation== ==Crazyflie Model Development and Verification== ==Developing New Controllers for the Crazyflie (pending Model Development)== ==Develop Communications Network Between Crazyflies== ==Trilateration Position Estimation using a Swarm== ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> ddf63c7686099987924458021b1e433d541bab19 174 173 2016-07-28T19:28:17Z Jnoronha 3 changed title and spacing wikitext text/x-wiki Here we will go into more depth on what each of these projects would require: ==Migrating Swarm Client PID's to Firmware== ===Focus Area=== '''Firmware Programming and Communication Protocols''' *This project requires heavy modification of the Firmware and Communication systems inside the Crazyflie. ===Tasks=== ====Firmware==== *'''(HARD)''' Modifying [https://wiki.bitcraze.io/projects:crazyflie:crtp:commander Commander Packet Structure] to allow position data to be sent rather than pitch, roll, yaw, and thrust setpoints. *Modifying Firmware to pass the new position data into the correct place for use by the Firmware PID controllers. ====Client==== *Modify Swarm Client packet construction to match new commander packet protocol in Firmware *'''(EASY)''' Remove Controllers from callbacks and just send location packets to Crazyflies while still maintaining other functionality. ===Benefits=== *Significantly reduces Client-side computation and allows Crazyflie swarm to share the load. *'''Potential extension:''' Completely independent Crazyflie flight (i.e. No Client needed at all) ==Model Development/Verification and Tuning X, Y, and Z Location PID's== ===Focus Area=== '''Control Systems and Model Development/Verification''' *This project will require developing a model of the Crazyflie system and using the Model to calculate PID constants. ===Tasks=== *'''(HARD)''' Identify model Parameters for the Crazyflie *Construct model in Simulink and Verify simulation compared to test data *'''(EASY)''' Derive PID constants from verified model, test flight performance ===Benefits=== *'''VERIFIED MODEL!!''' We can do many things once we have a verified model of the system. *Flight performance will be greatly improved allowing more complex applications to be developed. *'''Potential extension:''' Path prediction algorithms and optimal pathing between points with obstacles ==Adding Parameter Support to Swarm Client== ===Focus Area=== '''Communications Protocols and Networking''' *This project will require Client-side software development to create helper functions for easy modification of parameters on the Crazyflie Firmware ===Tasks=== *Creating packet framework in the Client to replicate the [https://wiki.bitcraze.io/projects:crazyflie:firmware:comm_protocol#parameters parameters packet protocol] *Programming helper functions to make it simple to modify parameters **Ex. Write Parameter Value: <code>setParam(string "param_group.param_name", int set_value);</code> **Ex. Read Parameter Value: <code>readParam(string "param_group.param_name");</code> ===Benefits=== *Won't have to re-flash Firmware every time we want to test a parameter change (Improves Firmware testing efficiency) *Less Firmware modification if we can just write params during Client init. *'''Potential Extension:''' Tuning Firmware PID constants ==Threading Each USB Radio to speed up Computation== ==Crazyflie Model Development and Verification== ==Developing New Controllers for the Crazyflie (pending Model Development)== ==Develop Communications Network Between Crazyflies== ==Trilateration Position Estimation using a Swarm== ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 4c9de0a619154289f99b0550a16f76a190f9de7e 175 174 2016-07-28T19:29:04Z Jnoronha 3 removed duplicate model development wikitext text/x-wiki Here we will go into more depth on what each of these projects would require: ==Migrating Swarm Client PID's to Firmware== ===Focus Area=== '''Firmware Programming and Communication Protocols''' *This project requires heavy modification of the Firmware and Communication systems inside the Crazyflie. ===Tasks=== ====Firmware==== *'''(HARD)''' Modifying [https://wiki.bitcraze.io/projects:crazyflie:crtp:commander Commander Packet Structure] to allow position data to be sent rather than pitch, roll, yaw, and thrust setpoints. *Modifying Firmware to pass the new position data into the correct place for use by the Firmware PID controllers. ====Client==== *Modify Swarm Client packet construction to match new commander packet protocol in Firmware *'''(EASY)''' Remove Controllers from callbacks and just send location packets to Crazyflies while still maintaining other functionality. ===Benefits=== *Significantly reduces Client-side computation and allows Crazyflie swarm to share the load. *'''Potential extension:''' Completely independent Crazyflie flight (i.e. No Client needed at all) ==Model Development/Verification and Tuning X, Y, and Z Location PID's== ===Focus Area=== '''Control Systems and Model Development/Verification''' *This project will require developing a model of the Crazyflie system and using the Model to calculate PID constants. ===Tasks=== *'''(HARD)''' Identify model Parameters for the Crazyflie *Construct model in Simulink and Verify simulation compared to test data *'''(EASY)''' Derive PID constants from verified model, test flight performance ===Benefits=== *'''VERIFIED MODEL!!''' We can do many things once we have a verified model of the system. *Flight performance will be greatly improved allowing more complex applications to be developed. *'''Potential extension:''' Path prediction algorithms and optimal pathing between points with obstacles ==Adding Parameter Support to Swarm Client== ===Focus Area=== '''Communications Protocols and Networking''' *This project will require Client-side software development to create helper functions for easy modification of parameters on the Crazyflie Firmware ===Tasks=== *Creating packet framework in the Client to replicate the [https://wiki.bitcraze.io/projects:crazyflie:firmware:comm_protocol#parameters parameters packet protocol] *Programming helper functions to make it simple to modify parameters **Ex. Write Parameter Value: <code>setParam(string "param_group.param_name", int set_value);</code> **Ex. Read Parameter Value: <code>readParam(string "param_group.param_name");</code> ===Benefits=== *Won't have to re-flash Firmware every time we want to test a parameter change (Improves Firmware testing efficiency) *Less Firmware modification if we can just write params during Client init. *'''Potential Extension:''' Tuning Firmware PID constants ==Threading Each USB Radio to speed up Computation== ==Developing New Controllers for the Crazyflie (pending Model Development)== ==Develop Communications Network Between Crazyflies== ==Trilateration Position Estimation using a Swarm== ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 60fb278599b0974720dda95cfe9121d8e5fc86d3 176 175 2016-07-28T19:55:56Z Jnoronha 3 /* Threading Each USB Radio to speed up Computation */ completed wikitext text/x-wiki Here we will go into more depth on what each of these projects would require: ==Migrating Swarm Client PID's to Firmware== ===Focus Area=== '''Firmware Programming and Communication Protocols''' *This project requires heavy modification of the Firmware and Communication systems inside the Crazyflie. ===Tasks=== ====Firmware==== *'''(HARD)''' Modifying [https://wiki.bitcraze.io/projects:crazyflie:crtp:commander Commander Packet Structure] to allow position data to be sent rather than pitch, roll, yaw, and thrust setpoints. *Modifying Firmware to pass the new position data into the correct place for use by the Firmware PID controllers. ====Client==== *Modify Swarm Client packet construction to match new commander packet protocol in Firmware *'''(EASY)''' Remove Controllers from callbacks and just send location packets to Crazyflies while still maintaining other functionality. ===Benefits=== *Significantly reduces Client-side computation and allows Crazyflie swarm to share the load. *'''Potential extension:''' Completely independent Crazyflie flight (i.e. No Client needed at all) ==Model Development/Verification and Tuning X, Y, and Z Location PID's== ===Focus Area=== '''Control Systems and Model Development/Verification''' *This project will require developing a model of the Crazyflie system and using the Model to calculate PID constants. ===Tasks=== *'''(HARD)''' Identify model Parameters for the Crazyflie *Construct model in Simulink and Verify simulation compared to test data *'''(EASY)''' Derive PID constants from verified model, test flight performance ===Benefits=== *'''VERIFIED MODEL!!''' We can do many things once we have a verified model of the system. *Flight performance will be greatly improved allowing more complex applications to be developed. *'''Potential extension:''' Path prediction algorithms and optimal pathing between points with obstacles ==Adding Parameter Support to Swarm Client== ===Focus Area=== '''Communications Protocols and Networking''' *This project will require Client-side software development to create helper functions for easy modification of parameters on the Crazyflie Firmware ===Tasks=== *Creating packet framework in the Client to replicate the [https://wiki.bitcraze.io/projects:crazyflie:firmware:comm_protocol#parameters parameters packet protocol] *Programming helper functions to make it simple to modify parameters **Ex. Write Parameter Value: <code>setParam(string "param_group.param_name", int set_value);</code> **Ex. Read Parameter Value: <code>readParam(string "param_group.param_name");</code> ===Benefits=== *Won't have to re-flash Firmware every time we want to test a parameter change (Improves Firmware testing efficiency) *Less Firmware modification if we can just write params during Client init. *'''Potential Extension:''' Tuning Firmware PID constants ==Threading Each USB Radio to speed up Computation== ===Focus Area=== '''Computer Architecture and Parallelization''' *This project will require/develop a good understanding of parallel processing and computer architecture. ===Tasks=== *Apply threading to each USB Radio individually **A single Radio will be assigned at most 3 Crazyflies, and each thread will handle the corresponding Callbacks for those Crazyflies (which includes control calculations, Radio communications, and logging for each Crazyflie) *Troubleshoot any issues that come up with non-sequential program execution (shouldn't have problems) ===Benefits=== *Greatly reduces time required to complete a loop cycle (relative to number of Crazyflies in the Swarm) **Improves scalability of the Swarm since we don't need to worry about missing the Camera System new data timing deadline as the Swarm size increases *'''Potential Extension:''' Increasing Swarm size to Camera System capacity limit. ==Developing New Controllers for the Crazyflie (pending Model Development)== ==Develop Communications Network Between Crazyflies== ==Trilateration Position Estimation using a Swarm== ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 5babe2b06e38b78f59e64c5a25e67541b257925b Using Robotic Agriculture Data Acquisition (RADA) for Research Use 0 48 165 2016-07-28T19:07:53Z Pfuhing 5 New page: This page discusses the RADA platform for research used. If you want information about the RADA platform see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Ma... wikitext text/x-wiki This page discusses the RADA platform for research used. If you want information about the RADA platform see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Main_Page RADA Senior Design Project]. This page will discuss two important issues for using the RADA platform for research: 0cc541ea9253120a4eb228ced7944f04ddfdd39d 168 165 2016-07-28T19:09:56Z Pfuhing 5 [[Robotic Agriculture Data Acquisition (RADA)]] moved to [[Using Robotic Agriculture Data Acquisition (RADA) for Research Use]]: There is already a wiki for the RADA platform designed by a ECpE senior design team so the pages could get confusing wikitext text/x-wiki This page discusses the RADA platform for research used. If you want information about the RADA platform see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Main_Page RADA Senior Design Project]. This page will discuss two important issues for using the RADA platform for research: 0cc541ea9253120a4eb228ced7944f04ddfdd39d 170 168 2016-07-28T19:13:24Z Pfuhing 5 wikitext text/x-wiki This page discusses the RADA platform for research used. If you want information about the RADA platform see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Main_Page RADA Senior Design Project]. This page will discuss two important issues for using the RADA platform for research: [[Data Collection and Simulation Comparison]] 7da2e657cc615e5edbcc4d8f008a9edd1e02efb8 171 170 2016-07-28T19:15:40Z Pfuhing 5 wikitext text/x-wiki This page discusses the RADA platform for research used. If you want information about the RADA platform see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Main_Page RADA Senior Design Project]. This page will discuss two important issues for using the RADA platform for research: [[Data Collection and Simulation Comparison]] [[Setting up and Modifying RADA Simulations]] 67c813c5f63a5b763c72610cd093cf2db2fada4b 172 171 2016-07-28T19:20:40Z Pfuhing 5 wikitext text/x-wiki This page discusses the RADA platform for research used. If you want information about the RADA platform see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Main_Page RADA Senior Design Project]. This page will discuss two important issues for using the RADA platform for research: *[[Data Collection and Simulation Comparison]] *[[Setting up and Modifying RADA Simulations]] The page on data collection and simulation comparison will discus how to set a test of RADA and then take the logged data and compare it to a simulation of RADA in Simulink using the model developed for Paul Uhing's thesis. While the page on setting up and modifing RADA simulations will discuss how RADA Simulink simulations are currently structured and other important information for creating your own Simulink simulations of RADA. 086138a5c9ed2365ec2d4a88a5cb83a0f9f45b47 Robotic Agriculture Data Acquisition (RADA) 0 49 169 2016-07-28T19:09:56Z Pfuhing 5 [[Robotic Agriculture Data Acquisition (RADA)]] moved to [[Using Robotic Agriculture Data Acquisition (RADA) for Research Use]]: There is already a wiki for the RADA platform designed by a ECpE senior design team so the pages could get confusing wikitext text/x-wiki #REDIRECT [[Using Robotic Agriculture Data Acquisition (RADA) for Research Use]] 5d9cf3c6ce57071342a9c5a3b38d8e10104b1056 Crazyflie Swarm 0 2 177 130 2016-07-28T20:02:55Z Jnoronha 3 /* Future Project Ideas */ linked all future projects to detailed section wikitext text/x-wiki The Crazyflie Swarm is a Networked Control platform designed for students to learn more about control and for researchers that wish to apply their research in practice. Platform development was started during the Summer of 2015 and continues to this day. Here you will find descriptions on how the platform works, how you can use it, and how you can get involved in developing the platform further! == Frequently Asked Questions == For help with common problems and troubleshooting please see the [[FAQ]]. == Background == The Crazyflie Swarm platform is based off of the ''Crazyflie'' Nano-quadcopter produced and maintained by [https://www.bitcraze.io/ Bitcraze]. The ''Crazyflie'' is completely open-source so we are able to look at and modify any part of the code and customize it to our needs. === Major Platform Components: === [[Image: High_Level_Figure_(Single_Radio_Single_Crazyflie_NO_NUMBERS_CROPPED).jpg‎|thumb|right|A high level overview of the Crazyflie Platform]] *[[PC Client Software]] *[[Firmware]] *[[USB Radio]] == Modifying the Platform == *[[Controller]] *[[Logging]] *[[Keyboard Commands]] *[[USB Radio#Changing Radio Channel|Changing Radio Channel]] *[[Flight Modes]] *[[Callbacks]] *[[Adding a Crazyflie]] *[[:Firmware]] ==Future Project Ideas== The whole concept of this Platform is to constantly expand its capabilities. If you are interested in developing this platform further here are some ideas to get you started! Additional details on any of these ideas can be found on the [[Future Project Ideas]] page. *[[:Future Project Ideas#Migrating Swarm Client PID's to Firmware|Migrating Swarm Client PID's to Firmware]] *[[:Future Project Ideas#Model Development/Verification and Tuning X, Y, and Z Location PID's|Model Development/Verification and Tuning X, Y, and Z Location PID's]] *[[:Future Project Ideas#Adding Parameter Support to Swarm Client|Adding Parameter Support to Swarm Client]] *[[:Future Project Ideas#Threading Each USB Radio to speed up Computation|Threading Each USB Radio to speed up Computation]] *[[:Future Project Ideas#Developing New Controllers for the Crazyflie (pending Model Development)|Developing New Controllers for the Crazyflie (pending Model Development)]] *[[:Future Project Ideas#Develop Communications Network Between Crazyflies|Develop Communications Network Between Crazyflies]] *[[:Future Project Ideas#Trilateration Position Estimation using a Swarm|Trilateration Position Estimation using a Swarm]] == [https://wiki.bitcraze.io/ Bitcraze Wiki] == Bitcraze maintains their own wiki on the many Crazyflie systems. If you can't find what you are looking for here, chances are they will have something to help. 62a25abdef765390632d834cd4275d7928c13cda Data Collection and Simulation Comparison 0 50 178 2016-08-01T18:49:31Z Pfuhing 5 New page: '''Setting Up a RADA Test''' ---- wikitext text/x-wiki '''Setting Up a RADA Test''' ---- d2029e49fadfe80ffa3887c8accc48e88d58d2f2 179 178 2016-08-01T18:50:17Z Pfuhing 5 wikitext text/x-wiki This '''Setting Up a RADA Test''' ---- 526991677210742543a05c5bc11e23ee3297bcb3 180 179 2016-08-01T18:55:00Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == e3bccf8523f70597e854b771f4a0c756f7dde6ac 181 180 2016-08-01T19:06:56Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == === Charging batteries === === Setting up the camera system === === Building Software === === Turing on RADA === === Connecting to RADA === == Testing RADA == === Running the first test after power up === === Running additional tests === === Measuring battery voltages === === Locating and retrieving log files === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB work space for simulation === === Running simulations and storing results === === Plotting results === 4f0e8ae541549903e5fc046f5fc3cb61bb427e72 182 181 2016-08-01T19:40:07Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. [[Image: High_Level_Figure_(Single_Radio_Single_Crazyflie_NO_NUMBERS_CROPPED).jpg‎|thumb|right|A high level overview of the Crazyflie Platform]] === Setting up the camera system === === Building Software === === Turing on RADA === === Connecting to RADA === == Testing RADA == === Running the first test after power up === === Running additional tests === === Measuring battery voltages === === Locating and retrieving log files === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === ac842f683442d9a4ff0e12445e8dc3ed3bacbd4f 185 182 2016-08-01T19:55:28Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. [[Image:ChargerPowerSuplyOff.JPG|thumb|right|Kepco Power Supply off]] === Setting up the camera system === === Building Software === === Turing on RADA === === Connecting to RADA === == Testing RADA == === Running the first test after power up === === Running additional tests === === Measuring battery voltages === === Locating and retrieving log files === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === 5725d1cca5781a6db4d7704b248b41d2f9680b37 191 185 2016-08-01T20:15:36Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|120px]] | [[Image:ChargerPowerSuplyOn.JPG|120px]] |- | Kepco Power Supply off | Kepco Power Supply on with correct voltage supply range. |} === Setting up the camera system === === Building Software === === Turing on RADA === === Connecting to RADA === == Testing RADA == === Running the first test after power up === === Running additional tests === === Measuring battery voltages === === Locating and retrieving log files === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === bb0bb1af6f8d4449213b9aed0fe20e46cbd71b12 193 191 2016-08-01T20:17:19Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} === Setting up the camera system === === Building Software === === Turing on RADA === === Connecting to RADA === == Testing RADA == === Running the first test after power up === === Running additional tests === === Measuring battery voltages === === Locating and retrieving log files === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === b14521faf68f4b08bd786b1820fa6f21f5553bf3 194 193 2016-08-01T20:26:14Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === === Building Software === === Turing on RADA === === Connecting to RADA === == Testing RADA == === Running the first test after power up === === Running additional tests === === Measuring battery voltages === === Locating and retrieving log files === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === b64a26ddc5023f2fab735a418876e13c022886c1 File:ChargerPowerSupplyOff.JPG 6 51 183 2016-08-01T19:41:25Z Pfuhing 5 Charging battery help wikitext text/x-wiki Charging battery help 3b2df7503b8c991c002decc5e33da101c1d8529b 186 183 2016-08-01T20:01:06Z Pfuhing 5 uploaded a new version of "[[Image:ChargerPowerSupplyOff.JPG]]" wikitext text/x-wiki Charging battery help 3b2df7503b8c991c002decc5e33da101c1d8529b 187 186 2016-08-01T20:02:01Z Pfuhing 5 wikitext text/x-wiki {{Rotate |degree=90 }} Charging battery help e51caeb9a637e1fa85fc6b001557c2613c283549 188 187 2016-08-01T20:02:16Z Pfuhing 5 wikitext text/x-wiki {{Rotate |degree=90 }}Charging battery help e3646ca64bb9f640ee7eb1610c4afcd228e60467 189 188 2016-08-01T20:05:12Z Pfuhing 5 uploaded a new version of "[[Image:ChargerPowerSupplyOff.JPG]]" wikitext text/x-wiki {{Rotate |degree=90 }}Charging battery help e3646ca64bb9f640ee7eb1610c4afcd228e60467 190 189 2016-08-01T20:09:55Z Pfuhing 5 uploaded a new version of "[[Image:ChargerPowerSupplyOff.JPG]]" wikitext text/x-wiki {{Rotate |degree=90 }}Charging battery help e3646ca64bb9f640ee7eb1610c4afcd228e60467 File:ChargerPowerSuplyOn.JPG 6 52 184 2016-08-01T19:42:01Z Pfuhing 5 charging help wikitext text/x-wiki charging help 9b31ff62f8d68aa89f96952e188a204c71e3d34d 192 184 2016-08-01T20:15:56Z Pfuhing 5 uploaded a new version of "[[Image:ChargerPowerSuplyOn.JPG]]" wikitext text/x-wiki charging help 9b31ff62f8d68aa89f96952e188a204c71e3d34d File:TrackingTools shortcut.PNG 6 53 195 2016-08-01T20:28:54Z Pfuhing 5 image of tracking tools short cut wikitext text/x-wiki image of tracking tools short cut bc1a7751159915d63891137515d0c1adfef1a622 File:NewTrackingTools.PNG 6 54 196 2016-08-01T20:31:15Z Pfuhing 5 Opening tracking tools wikitext text/x-wiki Opening tracking tools c5f6b14de4a006d80563f6b63fceca69522ac48c File:OpeningProject.PNG 6 55 197 2016-08-01T20:31:58Z Pfuhing 5 Open a tracking tools project wikitext text/x-wiki Open a tracking tools project e22b4d0ce5b40fb5c1a9cd40f9ffde1e0f1c15f9 File:Opening trackables.PNG 6 56 198 2016-08-01T20:33:57Z Pfuhing 5 open trackable constellations saved as a separate file wikitext text/x-wiki open trackable constellations saved as a separate file 1e27513b37350634e4140335c5ea561b2dc75052 File:SelectingUAV.PNG 6 57 199 2016-08-01T20:36:16Z Pfuhing 5 Selecting a teckable constellation wikitext text/x-wiki Selecting a teckable constellation 2aa4e817d01badeeff30392e6b023dc91150ccac File:Uav realTimeInfo.PNG 6 58 200 2016-08-01T20:36:57Z Pfuhing 5 checking the current orrientaiton of a trackable wikitext text/x-wiki checking the current orrientaiton of a trackable f6e56b04d94660fc09a4d6f31604c098571143d4 File:Uav ResetOrientation.PNG 6 59 201 2016-08-01T20:40:40Z Pfuhing 5 Reset orientation of constellation wikitext text/x-wiki Reset orientation of constellation 5cd1cd1bef7bc60c71010f19d247996033d94d11 Data Collection and Simulation Comparison 0 50 202 194 2016-08-01T20:53:28Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking TOlls in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|left|Tracking Tools shortcut]] === Building Software === === Turing on RADA === === Connecting to RADA === == Testing RADA == === Running the first test after power up === === Running additional tests === === Measuring battery voltages === === Locating and retrieving log files === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === 36defb4796fb92832ce0d5905d339343d27f6bfa 203 202 2016-08-01T21:50:46Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like TrackingToolsProject YYYY-MM-DD timeStamp.ttp. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is TrackingToolsProject 2015-09-23 2.30pm.ttp. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to File->Open and another pop up window will open. Navigate back to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like RADA_entireSystem_M_D_YYYY.tra. The most recent one as of August 1st, 2016 is RADA_entireSystem_7_8_2016.tra. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under Project Explorer->Trackables. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the Trackables Tab on the right side of the screen. For the current position and orientation look at the Real-Time Info sub -tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in Real-Time Info). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in REal-Time Info). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the Orientation tab (next to Real-Time Info tab) and click on Reset To Current Orientation button - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to File->Save Trakables... and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === === Turing on RADA === === Connecting to RADA === == Testing RADA == === Running the first test after power up === === Running additional tests === === Measuring battery voltages === === Locating and retrieving log files === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === 7b32d171d4ffdd540e8b59304bd44d61acb4a6cd 204 203 2016-08-02T00:37:03Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like TrackingToolsProject YYYY-MM-DD timeStamp.ttp. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is TrackingToolsProject 2015-09-23 2.30pm.ttp. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to File->Open and another pop up window will open. Navigate back to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like RADA_entireSystem_M_D_YYYY.tra. The most recent one as of August 1st, 2016 is RADA_entireSystem_7_8_2016.tra. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under Project Explorer->Trackables. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the Trackables Tab on the right side of the screen. For the current position and orientation look at the Real-Time Info sub -tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in Real-Time Info). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in REal-Time Info). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the Orientation tab (next to Real-Time Info tab) and click on Reset To Current Orientation button - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to File->Save Trakables... and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want === Turing on RADA === === Connecting to RADA === == Testing RADA == === Running the first test after power up === === Running additional tests === === Measuring battery voltages === === Locating and retrieving log files === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === 6121a33f5e5bf00e74ebc529592af5d9586f7e11 205 204 2016-08-02T00:46:23Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like TrackingToolsProject YYYY-MM-DD timeStamp.ttp. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is TrackingToolsProject 2015-09-23 2.30pm.ttp. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to File->Open and another pop up window will open. Navigate back to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like RADA_entireSystem_M_D_YYYY.tra. The most recent one as of August 1st, 2016 is RADA_entireSystem_7_8_2016.tra. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under Project Explorer->Trackables. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the Trackables Tab on the right side of the screen. For the current position and orientation look at the Real-Time Info sub -tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in Real-Time Info). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in REal-Time Info). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the Orientation tab (next to Real-Time Info tab) and click on Reset To Current Orientation button - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to File->Save Trakables... and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot Below is a compiler macro options for main.cpp: === Turing on RADA === === Connecting to RADA === == Testing RADA == === Running the first test after power up === === Running additional tests === === Measuring battery voltages === === Locating and retrieving log files === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === 675443722497f710124ee0ea08f0e223acbf5a89 206 205 2016-08-02T00:56:59Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like TrackingToolsProject YYYY-MM-DD timeStamp.ttp. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is TrackingToolsProject 2015-09-23 2.30pm.ttp. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to File->Open and another pop up window will open. Navigate back to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like RADA_entireSystem_M_D_YYYY.tra. The most recent one as of August 1st, 2016 is RADA_entireSystem_7_8_2016.tra. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under Project Explorer->Trackables. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the Trackables Tab on the right side of the screen. For the current position and orientation look at the Real-Time Info sub -tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in Real-Time Info). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in REal-Time Info). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the Orientation tab (next to Real-Time Info tab) and click on Reset To Current Orientation button - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to File->Save Trakables... and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot Below is a compiler macro options for main.cpp: *'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. *'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. *'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." *'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. *drop10 *drop30 *drop50 *mot50 *RADAlqi *RADAlqi_est *rada_lqg *rada_split_lqg *rada_split_lqg_ol *yaw_off *accR *posRamp === Turing on RADA === === Connecting to RADA === == Testing RADA == === Running the first test after power up === === Running additional tests === === Measuring battery voltages === === Locating and retrieving log files === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === 754c52a78c73b04d4b5e0991feebc3e5c410ded6 207 206 2016-08-02T00:59:55Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like TrackingToolsProject YYYY-MM-DD timeStamp.ttp. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is TrackingToolsProject 2015-09-23 2.30pm.ttp. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to File->Open and another pop up window will open. Navigate back to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like RADA_entireSystem_M_D_YYYY.tra. The most recent one as of August 1st, 2016 is RADA_entireSystem_7_8_2016.tra. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under Project Explorer->Trackables. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the Trackables Tab on the right side of the screen. For the current position and orientation look at the Real-Time Info sub -tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in Real-Time Info). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in REal-Time Info). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the Orientation tab (next to Real-Time Info tab) and click on Reset To Current Orientation button - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to File->Save Trakables... and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot Below is a compiler macro options for main.cpp: *'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. *'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. *'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." *'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. *'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. *'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. *'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. *mot50 *RADAlqi *RADAlqi_est *rada_lqg *rada_split_lqg *rada_split_lqg_ol *yaw_off *accR *posRamp === Turing on RADA === === Connecting to RADA === == Testing RADA == === Running the first test after power up === === Running additional tests === === Measuring battery voltages === === Locating and retrieving log files === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === 8943e83fdea6e821a7046d2a4e7da2cde7acf9bc 208 207 2016-08-02T01:03:48Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like TrackingToolsProject YYYY-MM-DD timeStamp.ttp. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is TrackingToolsProject 2015-09-23 2.30pm.ttp. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to File->Open and another pop up window will open. Navigate back to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like RADA_entireSystem_M_D_YYYY.tra. The most recent one as of August 1st, 2016 is RADA_entireSystem_7_8_2016.tra. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under Project Explorer->Trackables. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the Trackables Tab on the right side of the screen. For the current position and orientation look at the Real-Time Info sub -tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in Real-Time Info). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in REal-Time Info). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the Orientation tab (next to Real-Time Info tab) and click on Reset To Current Orientation button - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to File->Save Trakables... and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot Below is a compiler macro options for main.cpp: *'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. *'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. *'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." *'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. *'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. *'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. *'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. *'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. *'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. *'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. *rada_lqg *rada_split_lqg *rada_split_lqg_ol *yaw_off *accR *posRamp === Turing on RADA === === Connecting to RADA === == Testing RADA == === Running the first test after power up === === Running additional tests === === Measuring battery voltages === === Locating and retrieving log files === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === 22b1ef9f98a08da0307056859ebc0ea4d62fff8d 209 208 2016-08-02T01:25:23Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like TrackingToolsProject YYYY-MM-DD timeStamp.ttp. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is TrackingToolsProject 2015-09-23 2.30pm.ttp. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to File->Open and another pop up window will open. Navigate back to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like RADA_entireSystem_M_D_YYYY.tra. The most recent one as of August 1st, 2016 is RADA_entireSystem_7_8_2016.tra. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under Project Explorer->Trackables. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the Trackables Tab on the right side of the screen. For the current position and orientation look at the Real-Time Info sub -tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in Real-Time Info). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in REal-Time Info). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the Orientation tab (next to Real-Time Info tab) and click on Reset To Current Orientation button - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to File->Save Trakables... and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot Below is a compiler macro options for main.cpp: *'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. *'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. *'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." *'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. *'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. *'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. *'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. *'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. *'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. *'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. *'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. *'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. *'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. *'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. *'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. * If no controller selection is made all controllers revert to PID controllers === Turing on RADA === === Connecting to RADA === == Testing RADA == === Running the first test after power up === === Running additional tests === === Measuring battery voltages === === Locating and retrieving log files === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === db455d585115e9a1246c75ef1a32b86166b57ba1 210 209 2016-08-02T01:26:43Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like TrackingToolsProject YYYY-MM-DD timeStamp.ttp. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is TrackingToolsProject 2015-09-23 2.30pm.ttp. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to File->Open and another pop up window will open. Navigate back to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like RADA_entireSystem_M_D_YYYY.tra. The most recent one as of August 1st, 2016 is RADA_entireSystem_7_8_2016.tra. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under Project Explorer->Trackables. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the Trackables Tab on the right side of the screen. For the current position and orientation look at the Real-Time Info sub -tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in Real-Time Info). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in REal-Time Info). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the Orientation tab (next to Real-Time Info tab) and click on Reset To Current Orientation button - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to File->Save Trakables... and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers === Turing on RADA === === Connecting to RADA === == Testing RADA == === Running the first test after power up === === Running additional tests === === Measuring battery voltages === === Locating and retrieving log files === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === 6992a91adfabfc2b2b95fa992c0527fa9844ccf2 211 210 2016-08-02T01:41:19Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like TrackingToolsProject YYYY-MM-DD timeStamp.ttp. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is TrackingToolsProject 2015-09-23 2.30pm.ttp. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to File->Open and another pop up window will open. Navigate back to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like RADA_entireSystem_M_D_YYYY.tra. The most recent one as of August 1st, 2016 is RADA_entireSystem_7_8_2016.tra. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under Project Explorer->Trackables. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the Trackables Tab on the right side of the screen. For the current position and orientation look at the Real-Time Info sub -tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in Real-Time Info). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in REal-Time Info). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the Orientation tab (next to Real-Time Info tab) and click on Reset To Current Orientation button - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to File->Save Trakables... and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packed drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss Here just type: make. The code will compile for your desired mode. FOr setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA senior Design wiki. The corect define === Turing on RADA === === Connecting to RADA === == Testing RADA == === Running the first test after power up === === Running additional tests === === Measuring battery voltages === === Locating and retrieving log files === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === 14f01a45183d49d9a035029d8f8bde25cd4b76a3 214 211 2016-08-02T01:52:43Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like TrackingToolsProject YYYY-MM-DD timeStamp.ttp. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is TrackingToolsProject 2015-09-23 2.30pm.ttp. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to File->Open and another pop up window will open. Navigate back to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like RADA_entireSystem_M_D_YYYY.tra. The most recent one as of August 1st, 2016 is RADA_entireSystem_7_8_2016.tra. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under Project Explorer->Trackables. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the Trackables Tab on the right side of the screen. For the current position and orientation look at the Real-Time Info sub -tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in Real-Time Info). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in REal-Time Info). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the Orientation tab (next to Real-Time Info tab) and click on Reset To Current Orientation button - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to File->Save Trakables... and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packed drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss Here just type: make. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in /home/shared/MainProject. The /home/shared directory is setup as a network file share (NFS). [[Image:ComplingRADACode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have fond that even on a good strt the ''[ok]'' messages will still print. === Turing on RADA === === Connecting to RADA === == Testing RADA == === Running the first test after power up === === Running additional tests === === Measuring battery voltages === === Locating and retrieving log files === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === 8d081441065f2eec4c47583d7d2b4e6641b50bb9 215 214 2016-08-02T01:53:25Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like TrackingToolsProject YYYY-MM-DD timeStamp.ttp. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is TrackingToolsProject 2015-09-23 2.30pm.ttp. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to File->Open and another pop up window will open. Navigate back to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like RADA_entireSystem_M_D_YYYY.tra. The most recent one as of August 1st, 2016 is RADA_entireSystem_7_8_2016.tra. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under Project Explorer->Trackables. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the Trackables Tab on the right side of the screen. For the current position and orientation look at the Real-Time Info sub -tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in Real-Time Info). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in REal-Time Info). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the Orientation tab (next to Real-Time Info tab) and click on Reset To Current Orientation button - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to File->Save Trakables... and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packed drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss Here just type: make. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in /home/shared/MainProject. The /home/shared directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have fond that even on a good strt the ''[ok]'' messages will still print. === Turing on RADA === === Connecting to RADA === == Testing RADA == === Running the first test after power up === === Running additional tests === === Measuring battery voltages === === Locating and retrieving log files === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === 31bad6d285f6fd26d4b53eb7a223a36279943293 217 215 2016-08-02T02:06:17Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like TrackingToolsProject YYYY-MM-DD timeStamp.ttp. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is TrackingToolsProject 2015-09-23 2.30pm.ttp. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to File->Open and another pop up window will open. Navigate back to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like RADA_entireSystem_M_D_YYYY.tra. The most recent one as of August 1st, 2016 is RADA_entireSystem_7_8_2016.tra. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under Project Explorer->Trackables. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the Trackables Tab on the right side of the screen. For the current position and orientation look at the Real-Time Info sub -tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in Real-Time Info). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in REal-Time Info). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the Orientation tab (next to Real-Time Info tab) and click on Reset To Current Orientation button - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to File->Save Trakables... and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packed drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss Here just type: make. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in /home/shared/MainProject. The /home/shared directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have fond that even on a good strt the ''[ok]'' messages will still print. === Turing on RADA === Turing on Eris is fairly simple. eAch system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the swiches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you only the WIFI adapter or Ethernet plugged in at the same time or VRPN my listen to the camera data broadcast over both connects which could cause problems. === Connecting to RADA === == Testing RADA == === Running the first test after power up === === Running additional tests === === Measuring battery voltages === === Locating and retrieving log files === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === c257bb102eb98ed126090e8a0668a1463332c054 218 217 2016-08-02T02:11:20Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like TrackingToolsProject YYYY-MM-DD timeStamp.ttp. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is TrackingToolsProject 2015-09-23 2.30pm.ttp. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to File->Open and another pop up window will open. Navigate back to D:\Optitrack_Configuration (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like RADA_entireSystem_M_D_YYYY.tra. The most recent one as of August 1st, 2016 is RADA_entireSystem_7_8_2016.tra. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under Project Explorer->Trackables. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the Trackables Tab on the right side of the screen. For the current position and orientation look at the Real-Time Info sub -tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in Real-Time Info). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in REal-Time Info). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the Orientation tab (next to Real-Time Info tab) and click on Reset To Current Orientation button - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to File->Save Trakables... and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packed drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss Here just type: make. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in /home/shared/MainProject. The /home/shared directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have fond that even on a good strt the ''[ok]'' messages will still print. === Turing on RADA === Turing on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the swiches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you only the WIFI adapter or Ethernet plugged in at the same time or VRPN my listen to the camera data broadcast over both connects which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === == Testing RADA == === Running the first test after power up === === Running additional tests === === Measuring battery voltages === === Locating and retrieving log files === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === e619274a8603ea6767bb1b14f5f13db70a53e533 221 218 2016-08-02T02:22:17Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another pop up window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation button'' - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to ''File->Save Trakables...'' and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packed drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have fond that even on a good strt the ''[ok]'' messages will still print. === Turing on RADA === Turing on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the swiches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you only the WIFI adapter or Ethernet plugged in at the same time or VRPN my listen to the camera data broadcast over both connects which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup with out needing to close the connection. If you are using a WIFI connect use the command ''ssh root@192.168.0.53'' == Testing RADA == === Running the first test after power up === === Running additional tests === === Locating and retrieving log files === === Measuring battery voltages === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === 5616f1d64ec4a8ab70af727eaf6787dd052ff6da 222 221 2016-08-02T02:26:06Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another pop up window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation button'' - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to ''File->Save Trakables...'' and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packed drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have fond that even on a good strt the ''[ok]'' messages will still print. === Turing on RADA === Turing on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the swiches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you only the WIFI adapter or Ethernet plugged in at the same time or VRPN my listen to the camera data broadcast over both connects which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup with out needing to close the connection. If you are using a WIFI connect use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connaction use the command ''ssh root@192.168.0.54''. If the connection goes though you should be proped for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == === Running the first test after power up === === Running additional tests === === Locating and retrieving log files === === Measuring battery voltages === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === 69a4958246e715106983757dbd59d35aafee3b17 225 222 2016-08-02T16:57:32Z Pfuhing 5 /* Setting Up a RADA Test */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another pop up window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation button'' - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to ''File->Save Trakables...'' and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packed drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have fond that even on a good strt the ''[ok]'' messages will still print. === Turing on RADA === Turing on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the swiches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you only the WIFI adapter or Ethernet plugged in at the same time or VRPN my listen to the camera data broadcast over both connects which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup with out needing to close the connection. If you are using a WIFI connect use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connaction use the command ''ssh root@192.168.0.54''. If the connection goes though you should be proped for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == === Running the first test after power up === === Running additional tests === === Locating and retrieving log files === === Measuring battery voltages === == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === 2ab5c9a9a57014fddc31c492cf78f5119d6f4b21 230 225 2016-08-02T17:32:40Z Pfuhing 5 /* Testing RADA */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another pop up window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation button'' - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to ''File->Save Trakables...'' and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packed drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have fond that even on a good strt the ''[ok]'' messages will still print. === Turing on RADA === Turing on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the swiches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you only the WIFI adapter or Ethernet plugged in at the same time or VRPN my listen to the camera data broadcast over both connects which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup with out needing to close the connection. If you are using a WIFI connect use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connaction use the command ''ssh root@192.168.0.54''. If the connection goes though you should be proped for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the first test after power up === For the firs test after powering on Eris a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect the the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell scrip will setup the NFS, load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject and runs the executable. Once the user exits the executable the log file produces is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see an warning that when coping the log file Eris couldn't maintain the file permisiion settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This Date stamp uses date on Eris which is currently in June of 2008 as of August 2nd, 2016. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode. This shell scrip is run by using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA, you will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after start up you don't need to run this script. See the Section about Running additional tests below. === Testing Modes === ==== Robot Control Model ==== ==== Tuning Mode ==== ==== Box Step Mode ==== === Running additional Tests === === Locating and retrieving log files === === Measuring battery voltages === ==== Wheel Battery ==== ==== Quad Battery ==== == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === f6a85f9ce611f12015cc18b057d2a357deacc98a 231 230 2016-08-02T18:20:22Z Pfuhing 5 /* Testing RADA */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another pop up window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation button'' - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to ''File->Save Trakables...'' and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packed drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have fond that even on a good strt the ''[ok]'' messages will still print. === Turing on RADA === Turing on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the swiches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you only the WIFI adapter or Ethernet plugged in at the same time or VRPN my listen to the camera data broadcast over both connects which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup with out needing to close the connection. If you are using a WIFI connect use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connaction use the command ''ssh root@192.168.0.54''. If the connection goes though you should be proped for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the first test after power up === For the firs test after powering on Eris a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect the the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell scrip will setup the NFS, load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject and runs the executable. Once the user exits the executable the log file produces is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see an warning that when coping the log file Eris couldn't maintain the file permisiion settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This Date stamp uses date on Eris which is currently in June of 2008 as of August 2nd, 2016. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA, you will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after start up you don't need to run this script. See the Section about Running additional tests below. [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode you can use the following commands to enter the desired mode with a three second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode, this will only really work when using PIDs to control the pendulum. -''b'' : Enter Robot control mode, in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode, where the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file incase odd things happen somewhere. This just increments a counter so if you use it look for changes in the marker value. ==== Robot Control Model ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. ==== Box Step Mode ==== === Running additional Tests === === Locating and retrieving log files === === Measuring battery voltages === ==== Wheel Battery ==== ==== Quad Battery ==== == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === 6bd19381a57788ca07631cf9b062a6ebce7be93f 239 231 2016-08-02T19:35:31Z Pfuhing 5 /* Testing RADA */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another pop up window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation button'' - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to ''File->Save Trakables...'' and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packed drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have fond that even on a good strt the ''[ok]'' messages will still print. === Turing on RADA === Turing on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the swiches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you only the WIFI adapter or Ethernet plugged in at the same time or VRPN my listen to the camera data broadcast over both connects which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup with out needing to close the connection. If you are using a WIFI connect use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connaction use the command ''ssh root@192.168.0.54''. If the connection goes though you should be proped for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the first test after power up === For the firs test after powering on Eris a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect the the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell scrip will setup the NFS, load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject and runs the executable. Once the user exits the executable the log file produces is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see an warning that when coping the log file Eris couldn't maintain the file permisiion settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This Date stamp uses date on Eris which is currently in June of 2008 as of August 2nd, 2016. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA, you will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after start up you don't need to run this script. See the Section about Running additional tests below. [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode you can use the following commands to enter the desired mode with a three second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode, this will only really work when using PIDs to control the pendulum. -''b'' : Enter Robot control mode, in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode, where the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file incase odd things happen somewhere. This just increments a counter so if you use it look for changes in the marker value. ==== Robot Control Model ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box set mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use he same commands as Tuning Mode. === Running additional Tests === Once you have run one test with Eris on it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_stat_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result it is ready to test much quicker. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and retrieving log files === Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files are named like ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful of describing what the test was of or for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring battery voltages === ==== Wheel Battery ==== ==== Quad Battery ==== == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === 43f2a88f6bae58d0f15c79fb0252f8b8809671a9 243 239 2016-08-02T19:55:02Z Pfuhing 5 /* Measuring battery voltages */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another pop up window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation button'' - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to ''File->Save Trakables...'' and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packed drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have fond that even on a good strt the ''[ok]'' messages will still print. === Turing on RADA === Turing on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the swiches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you only the WIFI adapter or Ethernet plugged in at the same time or VRPN my listen to the camera data broadcast over both connects which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup with out needing to close the connection. If you are using a WIFI connect use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connaction use the command ''ssh root@192.168.0.54''. If the connection goes though you should be proped for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the first test after power up === For the firs test after powering on Eris a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect the the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell scrip will setup the NFS, load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject and runs the executable. Once the user exits the executable the log file produces is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see an warning that when coping the log file Eris couldn't maintain the file permisiion settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This Date stamp uses date on Eris which is currently in June of 2008 as of August 2nd, 2016. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA, you will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after start up you don't need to run this script. See the Section about Running additional tests below. [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode you can use the following commands to enter the desired mode with a three second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode, this will only really work when using PIDs to control the pendulum. -''b'' : Enter Robot control mode, in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode, where the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file incase odd things happen somewhere. This just increments a counter so if you use it look for changes in the marker value. ==== Robot Control Model ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box set mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use he same commands as Tuning Mode. === Running additional Tests === Once you have run one test with Eris on it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_stat_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result it is ready to test much quicker. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and retrieving log files === Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files are named like ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful of describing what the test was of or for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring battery voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there isn't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log is the headder. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value latter. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== ==== Quad Battery ==== == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === 2577eed86f07236e35eeb5657ff5bda849a8418b 249 243 2016-08-02T20:05:41Z Pfuhing 5 /* Wheel Battery */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another pop up window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation button'' - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to ''File->Save Trakables...'' and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packed drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have fond that even on a good strt the ''[ok]'' messages will still print. === Turing on RADA === Turing on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the swiches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you only the WIFI adapter or Ethernet plugged in at the same time or VRPN my listen to the camera data broadcast over both connects which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup with out needing to close the connection. If you are using a WIFI connect use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connaction use the command ''ssh root@192.168.0.54''. If the connection goes though you should be proped for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the first test after power up === For the firs test after powering on Eris a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect the the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell scrip will setup the NFS, load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject and runs the executable. Once the user exits the executable the log file produces is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see an warning that when coping the log file Eris couldn't maintain the file permisiion settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This Date stamp uses date on Eris which is currently in June of 2008 as of August 2nd, 2016. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA, you will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after start up you don't need to run this script. See the Section about Running additional tests below. [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode you can use the following commands to enter the desired mode with a three second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode, this will only really work when using PIDs to control the pendulum. -''b'' : Enter Robot control mode, in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode, where the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file incase odd things happen somewhere. This just increments a counter so if you use it look for changes in the marker value. ==== Robot Control Model ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box set mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use he same commands as Tuning Mode. === Running additional Tests === Once you have run one test with Eris on it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_stat_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result it is ready to test much quicker. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and retrieving log files === Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files are named like ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful of describing what the test was of or for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring battery voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there isn't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log is the headder. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value latter. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== 1. After test disconnect wheel battery from the system. 2. Measure voltage of battery using multimeter. [[Image:MeasureVwheel.jpg|800px]] You can use the plug used for charging the 2-cell Lipos but make sure to connect the plug to the multimeter before connecting the battery and disconnect the battery before disconnecting the plug from the mulitmeter. It is generally the best practice to give the multimeter a few minutes to allow for the voltage measurement to stabilize as the battery measurement tends to be a little low right after the test. ==== Quad Battery ==== == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === 874f3d9a7b563544a89f055673a46f05df21093c File:ComplingRADACode.png 6 60 212 2016-08-02T01:43:07Z Pfuhing 5 compile RADA code wikitext text/x-wiki compile RADA code e90628876cdd10f06ddb3e57033cf69feb7c7652 File:ErisCompliedCode-config.png 6 61 213 2016-08-02T01:43:41Z Pfuhing 5 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 File:ErisOnPhoto.jpg 6 62 216 2016-08-02T01:55:05Z Pfuhing 5 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 File:Ssh2Eris.png 6 63 219 2016-08-02T02:12:31Z Pfuhing 5 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 File:ClosingSSH.png 6 64 220 2016-08-02T02:14:34Z Pfuhing 5 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 PC Client Software 0 25 223 163 2016-08-02T16:38:32Z Jnoronha 3 /* Crazyflie Client GUI */ added crazyflie client file path wikitext text/x-wiki The PC Client software comes in many forms. The out-of-the-box Client is written in Python and has a Graphical User Interface (GUI). The GUI is well suited for beginners, but can only support a single Radio and a single Crazyflie at a time. The easiest way to start out is with the [https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze Virtual Machine (VM)], which comes with all the files and dependencies pre-installed and can run on any computer (Windows, Mac, Linux, etc.). For more advanced users who want to use the swarm capabilities of our platform will have to use the [[#Swarm Client|Swarm Client]] we developed in C and C++. ==[https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze VM]== ('''Note:''' The VM is updated frequently so the information below may be different than the current VM) The Bitcraze wiki has a tutorial on [https://wiki.bitcraze.io/projects:virtualmachine:tutorials:vmware-win7 installing the VM]. Along with another tutorial on how to get started [https://www.bitcraze.io/getting-started-with-development/ using the VM]. These are both very simple starting guides that will help you become familiar with the VM. ===Crazyflie Client GUI=== On the VM you can find the Crazyflie Client Graphical User Interface (GUI). To run the Client you want to open a terminal and navigate to <code>/home/bitcraze/Desktop/projects/crazyflie-clients-python/</code> and then run the command <code>sudo ./bin/cfclient</code> (Alternatively, you can use the desktop to navigate to the folder and open a terminal there) Once you do that you should see something similar to this: [[Image:DefaultCrazyflieGUIMainScreen.JPG|500px]] This is the main screen of the Client GUI and there are many tabs and features that you can access directly from this screen. The most important parts of this screen are the following: #Connect Button #Bootloader (Crazyflie Drop Down -> Bootloader) #Plotter Tab #Log Blocks Tab #Parameters Tab ====Connect Button==== This is where you will scan for Crazyflies that are powered ON. All Crazyflies not already connected will show up in the popup [[Image:DefaultCrazyflieGUIConnectScreen.JPG|400px]] We get a return that says <code>radio://0/45/2M</code>, this line is the identifier string of the Crazyflie we are trying to connect to. What this is saying is that we got a return from a Radio (Radio 0 specifically), from a Crazyflie on Channel 45 using a data rate of 2Mbps. ====Bootloader==== This where you can install new Firmware to the Crazyflie. [[Image:DefaultCrazyflieGUIBootloader.JPG|500px]] The first thing you'll need to update is to build the Firmware version you want into a .bin file. You can do this by just running the <code>make</code> command in terminal while located inside the Firmware directory you have modified. Once you have that .bin file built you: #Open the bootloader shown #Hold down the power button on the Crazyflie 2.0 for around 3 seconds until the 2 blue LED's flash and alternate. This puts the Crazyflie in bootloader mode. ('''NOTE:''' Recommend having '''ALL other Crazyflies OFF''' or else it could accidentally flash both Crazyflies.) #Then hit ''Initiate bootloader cold boot'' (it should connect to the Crazyflie in bootloader mode after a few seconds, Status will change from 'Not Connected' to 'Connected') #Hit ''Browse'' and find the .bin file you built earlier. #Then click ''Program'' and wait for the progress bar to complete. #Restart the Crazyflie in Firmware mode and make sure it starts up normally, if something seems wrong just repeat steps 2 through 6 again. ====Logging Tab==== Once you connect to a Crazyflie you can monitor certain log variables that have been set up. You will see a plot of the data similar to this: [[Image:DefaultCrazyflieGUILoggerScreen.JPG|400px]] On this screen we can do the following things: *Dropdown Menu at the top of the screen **Select which log block you want to plot on screen. *Scale the X-axis of the plot by: **Range **Number of Samples **Time in Seconds **Manually *Scale the Y-axis by: **Automatically **Manual Range ====Parameters Tab==== This tab displays all the parameters currently set up on the Crazyflie Firmware. Once you connect to a Crazyflie it lists these parameters in a table format similar to below: [[Image:DefaultCrazyflieGUIParametersScreen.JPG|400px]] For each parameter we get its Name, Variable Type, Access Type (Read/Write), and its Current Value. We can also modify the parameter values on this screen in real-time and the changes will be sent to the Crazyflie automatically. ('''Note:''' Any parameter changes made on this screen are NOT preserved when you turn OFF the Crazyflie.) ==Swarm Client== The swarm Client is a re-creation of the Original Client but programmed in C and C++. The benefit of this is that *We use a unified language between Client and Firmware *Easily migrate this platform to any linux distribution that can install the Crazyflie dependencies. **Our platform code itself requires only the VRPN libraries and a generic C compiler. ===Using the Swarm Client=== The Swarm Client uses the terminal interface for User Input. [[Image:CrazyflieTerminalInitial.png|400px]] Here we see what the initial Terminal looks like before we do anything. :1. The first thing you want to do before any testing is to run the <code>sudo make</code> command in the Swarm Client directory. (Yes, the 'sudo' is necessary) ::This will make sure you have all the necessary dependencies, that the code is error free, and then it will build an executable (.exe) file of the Swarm Client code. An error free make will look something like this: ::[[Image:CrazyflieTerminalPostMake.png|400px]] ::There will be warnings, but those don't cause any issues right now. :2. Pre-Test Checklist ::*Camera System is Turned on and Crazyflie Trackables are opened and visible. ::*Radios are plugged into the USB Ports on the Client computer. ::*Crazyflies are ON and NOT in an Error State. :3. Run the executable file using the command <code>sudo ./eris_vrpn</code> in the same directory (Yes, the 'sudo' is necessary). This will start the program initialization and a bunch of status info will flood the screen. You will know the program is ready for input when you see the following: ::[[Image:CrazyflieTerminalProgramStarted.png|400px]] ::This means that the Crazyflie yaw has been synchronized with the Camera system and they are ready to fly. :4. Input a Keyboard Command ::This will depend on what you have programmed as the keyboard input commands. As of 7/19/16 we have the following Keyboard Commands active: ::*'1' - Rotates Yaw of Crazyflie1 +45 degrees ::*'2' - Rotates Yaw of Crazyflie1 -45 degrees ::*'q' - Ends Main Loop (OBSOLETE - Replaced with ctrl + c) ::*'e' - Landing Mode (for ALL Crazyflies) ::*'t' - Crazyflie1 Take-Off ::*'y' - Crazyflie2 Take-Off ::*'u' - Crazyflie3 Take-Off ::*'i' - Crazyflie4 Take-Off ::*'h' - Hand Gesture Mode (for ALL Crazyflies) ::*'m' - Mirror Mode (for ALL Crazyflies) ::*ctrl+c - Quits Program, performs all cleanup. ::An example of what this would look like in the Terminal is shown here: ::[[Image:CrazyflieTerminalKeyboardInput.png|400px]] ::So you can see we commanded all 4 Crazyflies to take off (t,y,u,i), then activated Landing Mode (e), then activated Hand Mode (h), and then Ended the Program (ctrl+c). :5. End Program when finished (ctrl+c) ::This will end the program loop, print the current battery levels, and Delete the Radio pointers (shown at the end of the previous figure) ===Makefile=== The Swarm Client is compiled by a simple makefile. So when you call ''sudo make'' this makefile converts the C++ code files into an executable (.exe) for us. <blockquote> <code> <pre> g++ = g++ -Wall all: eris_vrpn eris_vrpn: eris_vrpn.h eris_vrpn.cpp vrpn.h vrpn.cpp CCrazyflie.h CCrazyflie.cpp CCrazyRadio.h CCrazyRadio.cpp CCRTPPacket.h CCRTPPacket.cpp CTOC.h CTOC.cpp simple.cpp simple.h pid.h pid.c controller.h controller.c multicast.c $(g++) -g -O0 -o eris_vrpn eris_vrpn.cpp vrpn.cpp CCrazyflie.cpp CCrazyRadio.cpp CCRTPPacket.cpp CTOC.cpp simple.cpp pid.c controller.c multicast.c -lquat -lvrpn -lpthread -lusb-1.0 clean: rm -f *.o eris_vrpn </pre> </code> </blockquote> ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> a916a689881266eefae2c979116065ff9b62532e 224 223 2016-08-02T16:43:22Z Jnoronha 3 /* Connect Button */ modified return description to a list wikitext text/x-wiki The PC Client software comes in many forms. The out-of-the-box Client is written in Python and has a Graphical User Interface (GUI). The GUI is well suited for beginners, but can only support a single Radio and a single Crazyflie at a time. The easiest way to start out is with the [https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze Virtual Machine (VM)], which comes with all the files and dependencies pre-installed and can run on any computer (Windows, Mac, Linux, etc.). For more advanced users who want to use the swarm capabilities of our platform will have to use the [[#Swarm Client|Swarm Client]] we developed in C and C++. ==[https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze VM]== ('''Note:''' The VM is updated frequently so the information below may be different than the current VM) The Bitcraze wiki has a tutorial on [https://wiki.bitcraze.io/projects:virtualmachine:tutorials:vmware-win7 installing the VM]. Along with another tutorial on how to get started [https://www.bitcraze.io/getting-started-with-development/ using the VM]. These are both very simple starting guides that will help you become familiar with the VM. ===Crazyflie Client GUI=== On the VM you can find the Crazyflie Client Graphical User Interface (GUI). To run the Client you want to open a terminal and navigate to <code>/home/bitcraze/Desktop/projects/crazyflie-clients-python/</code> and then run the command <code>sudo ./bin/cfclient</code> (Alternatively, you can use the desktop to navigate to the folder and open a terminal there) Once you do that you should see something similar to this: [[Image:DefaultCrazyflieGUIMainScreen.JPG|500px]] This is the main screen of the Client GUI and there are many tabs and features that you can access directly from this screen. The most important parts of this screen are the following: #Connect Button #Bootloader (Crazyflie Drop Down -> Bootloader) #Plotter Tab #Log Blocks Tab #Parameters Tab ====Connect Button==== This is where you will scan for Crazyflies that are powered ON. All Crazyflies not already connected will show up in the popup [[Image:DefaultCrazyflieGUIConnectScreen.JPG|400px]] We get a return that says <code>radio://0/45/2M</code>, this line is the identifier string of the Crazyflie we are trying to connect to. What this is saying is that we got a return from: #Radio 0 (the first radio) #Crazyflie on Channel 45 #Using a data rate of 2Mbps ====Bootloader==== This where you can install new Firmware to the Crazyflie. [[Image:DefaultCrazyflieGUIBootloader.JPG|500px]] The first thing you'll need to update is to build the Firmware version you want into a .bin file. You can do this by just running the <code>make</code> command in terminal while located inside the Firmware directory you have modified. Once you have that .bin file built you: #Open the bootloader shown #Hold down the power button on the Crazyflie 2.0 for around 3 seconds until the 2 blue LED's flash and alternate. This puts the Crazyflie in bootloader mode. ('''NOTE:''' Recommend having '''ALL other Crazyflies OFF''' or else it could accidentally flash both Crazyflies.) #Then hit ''Initiate bootloader cold boot'' (it should connect to the Crazyflie in bootloader mode after a few seconds, Status will change from 'Not Connected' to 'Connected') #Hit ''Browse'' and find the .bin file you built earlier. #Then click ''Program'' and wait for the progress bar to complete. #Restart the Crazyflie in Firmware mode and make sure it starts up normally, if something seems wrong just repeat steps 2 through 6 again. ====Logging Tab==== Once you connect to a Crazyflie you can monitor certain log variables that have been set up. You will see a plot of the data similar to this: [[Image:DefaultCrazyflieGUILoggerScreen.JPG|400px]] On this screen we can do the following things: *Dropdown Menu at the top of the screen **Select which log block you want to plot on screen. *Scale the X-axis of the plot by: **Range **Number of Samples **Time in Seconds **Manually *Scale the Y-axis by: **Automatically **Manual Range ====Parameters Tab==== This tab displays all the parameters currently set up on the Crazyflie Firmware. Once you connect to a Crazyflie it lists these parameters in a table format similar to below: [[Image:DefaultCrazyflieGUIParametersScreen.JPG|400px]] For each parameter we get its Name, Variable Type, Access Type (Read/Write), and its Current Value. We can also modify the parameter values on this screen in real-time and the changes will be sent to the Crazyflie automatically. ('''Note:''' Any parameter changes made on this screen are NOT preserved when you turn OFF the Crazyflie.) ==Swarm Client== The swarm Client is a re-creation of the Original Client but programmed in C and C++. The benefit of this is that *We use a unified language between Client and Firmware *Easily migrate this platform to any linux distribution that can install the Crazyflie dependencies. **Our platform code itself requires only the VRPN libraries and a generic C compiler. ===Using the Swarm Client=== The Swarm Client uses the terminal interface for User Input. [[Image:CrazyflieTerminalInitial.png|400px]] Here we see what the initial Terminal looks like before we do anything. :1. The first thing you want to do before any testing is to run the <code>sudo make</code> command in the Swarm Client directory. (Yes, the 'sudo' is necessary) ::This will make sure you have all the necessary dependencies, that the code is error free, and then it will build an executable (.exe) file of the Swarm Client code. An error free make will look something like this: ::[[Image:CrazyflieTerminalPostMake.png|400px]] ::There will be warnings, but those don't cause any issues right now. :2. Pre-Test Checklist ::*Camera System is Turned on and Crazyflie Trackables are opened and visible. ::*Radios are plugged into the USB Ports on the Client computer. ::*Crazyflies are ON and NOT in an Error State. :3. Run the executable file using the command <code>sudo ./eris_vrpn</code> in the same directory (Yes, the 'sudo' is necessary). This will start the program initialization and a bunch of status info will flood the screen. You will know the program is ready for input when you see the following: ::[[Image:CrazyflieTerminalProgramStarted.png|400px]] ::This means that the Crazyflie yaw has been synchronized with the Camera system and they are ready to fly. :4. Input a Keyboard Command ::This will depend on what you have programmed as the keyboard input commands. As of 7/19/16 we have the following Keyboard Commands active: ::*'1' - Rotates Yaw of Crazyflie1 +45 degrees ::*'2' - Rotates Yaw of Crazyflie1 -45 degrees ::*'q' - Ends Main Loop (OBSOLETE - Replaced with ctrl + c) ::*'e' - Landing Mode (for ALL Crazyflies) ::*'t' - Crazyflie1 Take-Off ::*'y' - Crazyflie2 Take-Off ::*'u' - Crazyflie3 Take-Off ::*'i' - Crazyflie4 Take-Off ::*'h' - Hand Gesture Mode (for ALL Crazyflies) ::*'m' - Mirror Mode (for ALL Crazyflies) ::*ctrl+c - Quits Program, performs all cleanup. ::An example of what this would look like in the Terminal is shown here: ::[[Image:CrazyflieTerminalKeyboardInput.png|400px]] ::So you can see we commanded all 4 Crazyflies to take off (t,y,u,i), then activated Landing Mode (e), then activated Hand Mode (h), and then Ended the Program (ctrl+c). :5. End Program when finished (ctrl+c) ::This will end the program loop, print the current battery levels, and Delete the Radio pointers (shown at the end of the previous figure) ===Makefile=== The Swarm Client is compiled by a simple makefile. So when you call ''sudo make'' this makefile converts the C++ code files into an executable (.exe) for us. <blockquote> <code> <pre> g++ = g++ -Wall all: eris_vrpn eris_vrpn: eris_vrpn.h eris_vrpn.cpp vrpn.h vrpn.cpp CCrazyflie.h CCrazyflie.cpp CCrazyRadio.h CCrazyRadio.cpp CCRTPPacket.h CCRTPPacket.cpp CTOC.h CTOC.cpp simple.cpp simple.h pid.h pid.c controller.h controller.c multicast.c $(g++) -g -O0 -o eris_vrpn eris_vrpn.cpp vrpn.cpp CCrazyflie.cpp CCrazyRadio.cpp CCRTPPacket.cpp CTOC.cpp simple.cpp pid.c controller.c multicast.c -lquat -lvrpn -lpthread -lusb-1.0 clean: rm -f *.o eris_vrpn </pre> </code> </blockquote> ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> feeeaa521b431d71ff98bcfe34e34d5055badc18 File:StartingRADA initial.png 6 65 226 2016-08-02T17:23:04Z Pfuhing 5 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 File:StartingRADA2nd.png 6 66 227 2016-08-02T17:23:34Z Pfuhing 5 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Firmware 0 26 228 125 2016-08-02T17:23:36Z Jnoronha 3 /* Changing Yaw Mode in Firmware */ added yaw mode change modification code wikitext text/x-wiki Not much work has been done in the Firmware yet (as of 7/20/16). The few things we have been able to successfully modify are: #Creating New Log Blocks #Modifying the Default Yaw Mode #Adding and Modifying Parameter Values ==New Firmware Log Blocks== In the Crazyflie Firmware there is a generalized logging framework that allows us to make any group of variables into a log block. It makes things very easy to log. Here are a few examples: :'''IMPORTANT:''' If you want to create new Log groups in a file, make sure you include <code>#include "log.h"</code> at the top of the file. :Ex. 1. Magnometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(mag) LOG_ADD(LOG_FLOAT, x, &mag.x) LOG_ADD(LOG_FLOAT, y, &mag.y) LOG_ADD(LOG_FLOAT, z, &mag.z) LOG_GROUP_STOP(mag) </pre> </code> </blockquote> ::So with this code we have created a log block called 'mag' and it contains the X, Y, and Z measurements from the magnetometer sensor. :Ex. 2. Accelerometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(acc) LOG_ADD(LOG_FLOAT, x, &acc.x) LOG_ADD(LOG_FLOAT, y, &acc.y) LOG_ADD(LOG_FLOAT, z, &acc.z) LOG_ADD(LOG_FLOAT, zw, &accWZ) LOG_ADD(LOG_FLOAT, mag2, &accMAG) LOG_GROUP_STOP(acc) </pre> </code> </blockquote> ::Just like in the magnetometer block, here we have created a log group called 'acc' and inside this group we are logging the variables for the accelerometer's X, Y, and Z values as well as 2 other gravity based variables used for thrust compensation. ===Using New Log Blocks in Swarm Client=== Now that we have these new log blocks in the Firmware, we can [[:Logging#New Client Log Blocks|use log blocks in the Client]] ==Modify the Default Yaw Mode== There are 3 types of Yaw Modes available in the Firmware (as of 7/21/16), as shown (code in ''Firmware > modules > interface > commander.h'') <blockquote> <code> <pre> typedef enum { CAREFREE = 0, // Yaw is locked to world coordinates thus heading stays the same when yaw rotates PLUSMODE = 1, // Plus-mode. Motor M1 is defined as front XMODE = 2, // X-mode. M1 & M4 is defined as front } YawModeType; </pre> </code> </blockquote> :'''Note:''' The default mode for the Crazyflie 2.0 is ''XMODE''. The ''PLUSMODE'' is default for the Crazyflie 1.0, but can still be used on the Crazyflie 2.0 if desired. ===Carefree Mode=== ''CAREFREE'' mode is what our Crazyflie 2.0's are using, this mode applies a transformation to the Pitch and Roll setpoints depending on the angle of Yaw. We used to perform this calculation on the Client like this (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> #if USE_PR_YAW_CORRECT //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION (_/57.2958 converts DEG to RADIANS) xError2 = cos(correctedYaw2 / 57.2958)*(xPositionDesired2 - xPosition2) - sin(correctedYaw2 / 57.2958)*(yPositionDesired2 - yPosition2); yError2 = sin(correctedYaw2 / 57.2958)*(xPositionDesired2 - xPosition2) + cos(correctedYaw2 / 57.2958)*(yPositionDesired2 - yPosition2); #else xError2 = xPositionDesired2 - xPosition2; yError2 = yPositionDesired2 - yPosition2; #endif controllerSetXYError(&pidCtrl2, xError2, yError2); </pre> </code> </blockquote> This is no longer necessary on the Client because this is the exact same calculation ''CAREFREE'' mode performs on the Firmware. So this reduces the computation done on the Client in each Crazyflie Callback. ====Changing Yaw Mode in Firmware==== To change the Yaw Mode to ''CAREFREE'' mode we had to make the modification shown (code in ''Firmware > modules > interface > commander.h (line 36)''): :'''ORIGINAL:''' <blockquote> <code> <pre> #ifdef PLATFORM_CF1 #define DEFUALT_YAW_MODE PLUSMODE #else #define DEFUALT_YAW_MODE XMODE #endif </pre> </code> </blockquote> :'''MODIFIED:''' <blockquote> <code> <pre> #ifdef PLATFORM_CF1 #define DEFUALT_YAW_MODE PLUSMODE #else #define DEFUALT_YAW_MODE CAREFREE #endif </pre> </code> </blockquote> ::The code checks for which version Crazyflie you are using, either the original Crazyflie (<code>PLATFORM_CF1</code>), or the Crazyflie 2.0. We are using the Crazyflie 2.0 so we only care about the 2nd ''DEFAULT_YAW_MODE'', which we modified to ''CAREFREE'' mode as shown. ==New Firmware Parameter Groups== Parameter groups are very similar to Log groups with a few key differences. An example of a Parameter group is shown (code in ''Firmware > modules > src > commander.c''): :'''IMPORTANT:''' If you want to create new Parameter groups in a file, make sure you include <code>#include "param.h"</code> at the top of the file. <blockquote> <code> <pre> // Params for flight modes PARAM_GROUP_START(flightmode) PARAM_ADD(PARAM_UINT8, althold, &altHoldMode) PARAM_ADD(PARAM_UINT8, yawMode, &yawMode) PARAM_ADD(PARAM_UINT8, yawRst, &carefreeResetFront) PARAM_ADD(PARAM_UINT8, stabModeRoll, &stabilizationModeRoll) PARAM_ADD(PARAM_UINT8, stabModePitch, &stabilizationModePitch) PARAM_ADD(PARAM_UINT8, stabModeYaw, &stabilizationModeYaw) PARAM_GROUP_STOP(flightmode) </pre> </code> </blockquote> :So we create a parameter group called ''flightmode'' that contains the parameters listed. The difference between Log variables and Param variables is that for Param variables you need to specify the variable type (''PARAM_UINT8'' shown in the example). Some User Friendly Param Types are shown below (you can find more complex Param types in ''Firmware > modules > interface > param.h''). <blockquote> <code> <pre> // User-friendly macros #define PARAM_UINT8 (PARAM_1BYTE | PARAM_TYPE_INT | PARAM_UNSIGNED) #define PARAM_INT8 (PARAM_1BYTE | PARAM_TYPE_INT | PARAM_SIGNED) #define PARAM_UINT16 (PARAM_2BYTES | PARAM_TYPE_INT | PARAM_UNSIGNED) #define PARAM_INT16 (PARAM_2BYTES | PARAM_TYPE_INT | PARAM_SIGNED) #define PARAM_UINT32 (PARAM_4BYTES | PARAM_TYPE_INT | PARAM_UNSIGNED) #define PARAM_INT32 (PARAM_4BYTES | PARAM_TYPE_INT | PARAM_SIGNED) </pre> </code> </blockquote> ===Using Param Groups in Client=== This is not implemented yet (as of 7/21/16) but would be very nice to have. We could then tune Firmware PID constants without needing to flash the Firmware each time and much more. If someone would like to attempt to create this you can see the Bitcraze Wiki page on the [https://wiki.bitcraze.io/doc:crazyflie:crtp:param Params Protocol] for help on how to implement this. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 7feba85e4864c2dcc99100e9c3587155c8cbd601 247 228 2016-08-02T20:01:13Z Jnoronha 3 /* Changing Yaw Mode in Firmware */ added ellipses to yaw mode firmware change to show its a code section wikitext text/x-wiki Not much work has been done in the Firmware yet (as of 7/20/16). The few things we have been able to successfully modify are: #Creating New Log Blocks #Modifying the Default Yaw Mode #Adding and Modifying Parameter Values ==New Firmware Log Blocks== In the Crazyflie Firmware there is a generalized logging framework that allows us to make any group of variables into a log block. It makes things very easy to log. Here are a few examples: :'''IMPORTANT:''' If you want to create new Log groups in a file, make sure you include <code>#include "log.h"</code> at the top of the file. :Ex. 1. Magnometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(mag) LOG_ADD(LOG_FLOAT, x, &mag.x) LOG_ADD(LOG_FLOAT, y, &mag.y) LOG_ADD(LOG_FLOAT, z, &mag.z) LOG_GROUP_STOP(mag) </pre> </code> </blockquote> ::So with this code we have created a log block called 'mag' and it contains the X, Y, and Z measurements from the magnetometer sensor. :Ex. 2. Accelerometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(acc) LOG_ADD(LOG_FLOAT, x, &acc.x) LOG_ADD(LOG_FLOAT, y, &acc.y) LOG_ADD(LOG_FLOAT, z, &acc.z) LOG_ADD(LOG_FLOAT, zw, &accWZ) LOG_ADD(LOG_FLOAT, mag2, &accMAG) LOG_GROUP_STOP(acc) </pre> </code> </blockquote> ::Just like in the magnetometer block, here we have created a log group called 'acc' and inside this group we are logging the variables for the accelerometer's X, Y, and Z values as well as 2 other gravity based variables used for thrust compensation. ===Using New Log Blocks in Swarm Client=== Now that we have these new log blocks in the Firmware, we can [[:Logging#New Client Log Blocks|use log blocks in the Client]] ==Modify the Default Yaw Mode== There are 3 types of Yaw Modes available in the Firmware (as of 7/21/16), as shown (code in ''Firmware > modules > interface > commander.h'') <blockquote> <code> <pre> typedef enum { CAREFREE = 0, // Yaw is locked to world coordinates thus heading stays the same when yaw rotates PLUSMODE = 1, // Plus-mode. Motor M1 is defined as front XMODE = 2, // X-mode. M1 & M4 is defined as front } YawModeType; </pre> </code> </blockquote> :'''Note:''' The default mode for the Crazyflie 2.0 is ''XMODE''. The ''PLUSMODE'' is default for the Crazyflie 1.0, but can still be used on the Crazyflie 2.0 if desired. ===Carefree Mode=== ''CAREFREE'' mode is what our Crazyflie 2.0's are using, this mode applies a transformation to the Pitch and Roll setpoints depending on the angle of Yaw. We used to perform this calculation on the Client like this (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> #if USE_PR_YAW_CORRECT //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION (_/57.2958 converts DEG to RADIANS) xError2 = cos(correctedYaw2 / 57.2958)*(xPositionDesired2 - xPosition2) - sin(correctedYaw2 / 57.2958)*(yPositionDesired2 - yPosition2); yError2 = sin(correctedYaw2 / 57.2958)*(xPositionDesired2 - xPosition2) + cos(correctedYaw2 / 57.2958)*(yPositionDesired2 - yPosition2); #else xError2 = xPositionDesired2 - xPosition2; yError2 = yPositionDesired2 - yPosition2; #endif controllerSetXYError(&pidCtrl2, xError2, yError2); </pre> </code> </blockquote> This is no longer necessary on the Client because this is the exact same calculation ''CAREFREE'' mode performs on the Firmware. So this reduces the computation done on the Client in each Crazyflie Callback. ====Changing Yaw Mode in Firmware==== To change the Yaw Mode to ''CAREFREE'' mode we had to make the modification shown (code in ''Firmware > modules > interface > commander.h (line 36)''): :'''ORIGINAL:''' <blockquote> <code> <pre> ... #ifdef PLATFORM_CF1 #define DEFUALT_YAW_MODE PLUSMODE #else #define DEFUALT_YAW_MODE XMODE #endif ... </pre> </code> </blockquote> :'''MODIFIED:''' <blockquote> <code> <pre> ... #ifdef PLATFORM_CF1 #define DEFUALT_YAW_MODE PLUSMODE #else #define DEFUALT_YAW_MODE CAREFREE #endif ... </pre> </code> </blockquote> ::The code checks for which version Crazyflie you are using, either the original Crazyflie (<code>PLATFORM_CF1</code>), or the Crazyflie 2.0. We are using the Crazyflie 2.0 so we only care about the 2nd ''DEFAULT_YAW_MODE'', which we modified to ''CAREFREE'' mode as shown. ==New Firmware Parameter Groups== Parameter groups are very similar to Log groups with a few key differences. An example of a Parameter group is shown (code in ''Firmware > modules > src > commander.c''): :'''IMPORTANT:''' If you want to create new Parameter groups in a file, make sure you include <code>#include "param.h"</code> at the top of the file. <blockquote> <code> <pre> // Params for flight modes PARAM_GROUP_START(flightmode) PARAM_ADD(PARAM_UINT8, althold, &altHoldMode) PARAM_ADD(PARAM_UINT8, yawMode, &yawMode) PARAM_ADD(PARAM_UINT8, yawRst, &carefreeResetFront) PARAM_ADD(PARAM_UINT8, stabModeRoll, &stabilizationModeRoll) PARAM_ADD(PARAM_UINT8, stabModePitch, &stabilizationModePitch) PARAM_ADD(PARAM_UINT8, stabModeYaw, &stabilizationModeYaw) PARAM_GROUP_STOP(flightmode) </pre> </code> </blockquote> :So we create a parameter group called ''flightmode'' that contains the parameters listed. The difference between Log variables and Param variables is that for Param variables you need to specify the variable type (''PARAM_UINT8'' shown in the example). Some User Friendly Param Types are shown below (you can find more complex Param types in ''Firmware > modules > interface > param.h''). <blockquote> <code> <pre> // User-friendly macros #define PARAM_UINT8 (PARAM_1BYTE | PARAM_TYPE_INT | PARAM_UNSIGNED) #define PARAM_INT8 (PARAM_1BYTE | PARAM_TYPE_INT | PARAM_SIGNED) #define PARAM_UINT16 (PARAM_2BYTES | PARAM_TYPE_INT | PARAM_UNSIGNED) #define PARAM_INT16 (PARAM_2BYTES | PARAM_TYPE_INT | PARAM_SIGNED) #define PARAM_UINT32 (PARAM_4BYTES | PARAM_TYPE_INT | PARAM_UNSIGNED) #define PARAM_INT32 (PARAM_4BYTES | PARAM_TYPE_INT | PARAM_SIGNED) </pre> </code> </blockquote> ===Using Param Groups in Client=== This is not implemented yet (as of 7/21/16) but would be very nice to have. We could then tune Firmware PID constants without needing to flash the Firmware each time and much more. If someone would like to attempt to create this you can see the Bitcraze Wiki page on the [https://wiki.bitcraze.io/doc:crazyflie:crtp:param Params Protocol] for help on how to implement this. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 4ab6ab8c47112c7ffc89f8b8387e87decb80d16e 248 247 2016-08-02T20:02:41Z Jnoronha 3 /* Using Param Groups in Client */ linked param support future project idea wikitext text/x-wiki Not much work has been done in the Firmware yet (as of 7/20/16). The few things we have been able to successfully modify are: #Creating New Log Blocks #Modifying the Default Yaw Mode #Adding and Modifying Parameter Values ==New Firmware Log Blocks== In the Crazyflie Firmware there is a generalized logging framework that allows us to make any group of variables into a log block. It makes things very easy to log. Here are a few examples: :'''IMPORTANT:''' If you want to create new Log groups in a file, make sure you include <code>#include "log.h"</code> at the top of the file. :Ex. 1. Magnometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(mag) LOG_ADD(LOG_FLOAT, x, &mag.x) LOG_ADD(LOG_FLOAT, y, &mag.y) LOG_ADD(LOG_FLOAT, z, &mag.z) LOG_GROUP_STOP(mag) </pre> </code> </blockquote> ::So with this code we have created a log block called 'mag' and it contains the X, Y, and Z measurements from the magnetometer sensor. :Ex. 2. Accelerometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(acc) LOG_ADD(LOG_FLOAT, x, &acc.x) LOG_ADD(LOG_FLOAT, y, &acc.y) LOG_ADD(LOG_FLOAT, z, &acc.z) LOG_ADD(LOG_FLOAT, zw, &accWZ) LOG_ADD(LOG_FLOAT, mag2, &accMAG) LOG_GROUP_STOP(acc) </pre> </code> </blockquote> ::Just like in the magnetometer block, here we have created a log group called 'acc' and inside this group we are logging the variables for the accelerometer's X, Y, and Z values as well as 2 other gravity based variables used for thrust compensation. ===Using New Log Blocks in Swarm Client=== Now that we have these new log blocks in the Firmware, we can [[:Logging#New Client Log Blocks|use log blocks in the Client]] ==Modify the Default Yaw Mode== There are 3 types of Yaw Modes available in the Firmware (as of 7/21/16), as shown (code in ''Firmware > modules > interface > commander.h'') <blockquote> <code> <pre> typedef enum { CAREFREE = 0, // Yaw is locked to world coordinates thus heading stays the same when yaw rotates PLUSMODE = 1, // Plus-mode. Motor M1 is defined as front XMODE = 2, // X-mode. M1 & M4 is defined as front } YawModeType; </pre> </code> </blockquote> :'''Note:''' The default mode for the Crazyflie 2.0 is ''XMODE''. The ''PLUSMODE'' is default for the Crazyflie 1.0, but can still be used on the Crazyflie 2.0 if desired. ===Carefree Mode=== ''CAREFREE'' mode is what our Crazyflie 2.0's are using, this mode applies a transformation to the Pitch and Roll setpoints depending on the angle of Yaw. We used to perform this calculation on the Client like this (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> #if USE_PR_YAW_CORRECT //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION (_/57.2958 converts DEG to RADIANS) xError2 = cos(correctedYaw2 / 57.2958)*(xPositionDesired2 - xPosition2) - sin(correctedYaw2 / 57.2958)*(yPositionDesired2 - yPosition2); yError2 = sin(correctedYaw2 / 57.2958)*(xPositionDesired2 - xPosition2) + cos(correctedYaw2 / 57.2958)*(yPositionDesired2 - yPosition2); #else xError2 = xPositionDesired2 - xPosition2; yError2 = yPositionDesired2 - yPosition2; #endif controllerSetXYError(&pidCtrl2, xError2, yError2); </pre> </code> </blockquote> This is no longer necessary on the Client because this is the exact same calculation ''CAREFREE'' mode performs on the Firmware. So this reduces the computation done on the Client in each Crazyflie Callback. ====Changing Yaw Mode in Firmware==== To change the Yaw Mode to ''CAREFREE'' mode we had to make the modification shown (code in ''Firmware > modules > interface > commander.h (line 36)''): :'''ORIGINAL:''' <blockquote> <code> <pre> ... #ifdef PLATFORM_CF1 #define DEFUALT_YAW_MODE PLUSMODE #else #define DEFUALT_YAW_MODE XMODE #endif ... </pre> </code> </blockquote> :'''MODIFIED:''' <blockquote> <code> <pre> ... #ifdef PLATFORM_CF1 #define DEFUALT_YAW_MODE PLUSMODE #else #define DEFUALT_YAW_MODE CAREFREE #endif ... </pre> </code> </blockquote> ::The code checks for which version Crazyflie you are using, either the original Crazyflie (<code>PLATFORM_CF1</code>), or the Crazyflie 2.0. We are using the Crazyflie 2.0 so we only care about the 2nd ''DEFAULT_YAW_MODE'', which we modified to ''CAREFREE'' mode as shown. ==New Firmware Parameter Groups== Parameter groups are very similar to Log groups with a few key differences. An example of a Parameter group is shown (code in ''Firmware > modules > src > commander.c''): :'''IMPORTANT:''' If you want to create new Parameter groups in a file, make sure you include <code>#include "param.h"</code> at the top of the file. <blockquote> <code> <pre> // Params for flight modes PARAM_GROUP_START(flightmode) PARAM_ADD(PARAM_UINT8, althold, &altHoldMode) PARAM_ADD(PARAM_UINT8, yawMode, &yawMode) PARAM_ADD(PARAM_UINT8, yawRst, &carefreeResetFront) PARAM_ADD(PARAM_UINT8, stabModeRoll, &stabilizationModeRoll) PARAM_ADD(PARAM_UINT8, stabModePitch, &stabilizationModePitch) PARAM_ADD(PARAM_UINT8, stabModeYaw, &stabilizationModeYaw) PARAM_GROUP_STOP(flightmode) </pre> </code> </blockquote> :So we create a parameter group called ''flightmode'' that contains the parameters listed. The difference between Log variables and Param variables is that for Param variables you need to specify the variable type (''PARAM_UINT8'' shown in the example). Some User Friendly Param Types are shown below (you can find more complex Param types in ''Firmware > modules > interface > param.h''). <blockquote> <code> <pre> // User-friendly macros #define PARAM_UINT8 (PARAM_1BYTE | PARAM_TYPE_INT | PARAM_UNSIGNED) #define PARAM_INT8 (PARAM_1BYTE | PARAM_TYPE_INT | PARAM_SIGNED) #define PARAM_UINT16 (PARAM_2BYTES | PARAM_TYPE_INT | PARAM_UNSIGNED) #define PARAM_INT16 (PARAM_2BYTES | PARAM_TYPE_INT | PARAM_SIGNED) #define PARAM_UINT32 (PARAM_4BYTES | PARAM_TYPE_INT | PARAM_UNSIGNED) #define PARAM_INT32 (PARAM_4BYTES | PARAM_TYPE_INT | PARAM_SIGNED) </pre> </code> </blockquote> ===Using Param Groups in Client=== This is not implemented yet (as of 7/21/16) but would be very nice to have. We could then tune Firmware PID constants without needing to flash the Firmware each time and much more. If someone would like to [[:Future Project Ideas#Adding Parameter Support to Swarm Client|attempt to create this]] you can see the Bitcraze Wiki page on the [https://wiki.bitcraze.io/doc:crazyflie:crtp:param Params Protocol] for help on how to implement this. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 6eca72d50daef7a8c92078de18f462499c8bbae5 Controller 0 5 229 133 2016-08-02T17:27:06Z Jnoronha 3 /* State Estimator (Not Implemented Yet) */ added mention of a state feedback controller wikitext text/x-wiki The Crazyflie platform is completely customizable when it comes to the control design. As long as the controller can be written in C or C++, we can implement it in the Platform. This applies to both the controllers run on the PC Client and the controllers run on the Firmware of the Crazyflie. Originally the only controllers in the Platform were Firmware PID's that controlled the angular position and rates of the Crazyflie for hand flight. The original controller layout can be seen here [[#Original PID Controllers (Angular Rotation)|Original PID's]]. Below you will find documentation on the different types of Controllers that have been applied to the platform, organized by their location in the Platform. == Firmware == === Original PID Controllers (Angular Rotation) === Directly on the Crazyflie Firmware there are 5 PID controllers as seen here: [[Image:FirmwareOnlyPIDArchitecture.png|500px]] The Pitch and Roll angular position PID's receive constant setpoints from some outside source (gamepad controller or automated controller). The outputs of those angular position controllers is then fed into the angular rate controllers as shown. This final output is then fed into the Motor Command block which converts the angular rate setpoints into motor commands. ---- ===State Estimator (Not Implemented Yet)=== ('''***NOT YET IMPLEMENTED***''') Bitcraze is currently working on adding a state estimator and state-feedback controller onto the Firmware to handle control calculations instead of the PID. The code is in place but the controller is not yet used as of '''7/13/16'''. == PC Client == === Client PID Controllers (Position and Yaw) === The first controller implemented on the Client were 4 PID controllers used to stabilize the Crazyflie's position in X, Y, and Z, and angular position in Yaw respectively. These PID's feed directly into the Firmware PID's as seen here: [[Image:CompletePIDArchitectureFigure.png|500px]] The controllers inside the red box are the original PID controllers located on the Firmware as shown above in the [[#Original PID Controllers (Angular Rotation)|Original PID's]]. ====Initialize the PID's==== :1. To start we create a struct with all the necessary variables (code from ''pid.h''): <blockquote> <code> <pre> typedef struct { float desired; //< set point float error; //< error float prevError; //< previous error float integ; //< integral float deriv; //< derivative float kp; //< proportional gain float ki; //< integral gain float kd; //< derivative gain float outP; //< proportional output (debugging) float outI; //< integral output (debugging) float outD; //< derivative output (debugging) float iLimit; //< integral limit float iLimitLow; //< integral limit float dt; //< delta-time dt float angularLimit; //sets limit for how far Crazyflie can tip, to prevent flipping float angularLimitLow; //^ float thrustLimit; //Sets upper limit for Thrust Output (60000?) **? float thrustLimitLow; //Sets lower limit for thrust Output (10001) } PidObject; </pre> </code> </blockquote> :2. To simplify scaling up the code to multiple Crazyflies, we will create a <code> ControllerObject </code> that contains multiple PID structs as shown (code in ''controller.h''): <blockquote> <code> <pre> typedef struct { PidObject pidRoll; PidObject pidPitch; PidObject pidYaw; PidObject pidX; PidObject pidY; PidObject pidZ; bool isInit; } ControllerObject; </pre> </code> </blockquote> :3. Then we initialize the Objects to 0 at the start of each run (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> ControllerObject pidCtrl1 = { 0 }; // init all fields to zero ControllerObject pidCtrl2 = { 0 }; // init all fields to zero ControllerObject pidCtrl3 = { 0 }; // init all fields to zero ControllerObject pidCtrl4 = { 0 }; // init all fields to zero </pre> </code> </blockquote> :4. Then populate the PidObjects with the desired parameters (code in ''pid.c''): <blockquote> <code> <pre> void pidInit(PidObject* pid, const float desired, const float kp, const float ki, const float kd, const float dt) { pid->error = 0; pid->prevError = 0; pid->integ = 0; pid->deriv = 0; pid->desired = desired; pid->kp = kp; pid->ki = ki; pid->kd = kd; pid->iLimit = DEFAULT_PID_INTEGRATION_LIMIT; pid->iLimitLow = -DEFAULT_PID_INTEGRATION_LIMIT; pid->angularLimit = DEFAULT_PID_ANGLE_OUTPUT; pid->angularLimitLow = -DEFAULT_PID_ANGLE_OUTPUT; pid->thrustLimit = DEFAULT_PID_HIGH_THRUST_LIMIT; pid->thrustLimitLow = DEFAULT_PID_LOW_THRUST_LIMIT; pid->dt = dt; } </pre> </code> </blockquote> Using the above function for each of the <code>PidObjects</code> inside of the <code>ControllerObject</code> below (code in ''controller.c''): <blockquote> <code> <pre> void controllerInit( ControllerObject * ctrl ) { if(ctrl->isInit) return; pidInit(&ctrl->pidY, 0, PID_Y_KP, PID_Y_KI, PID_Y_KD, CAMERA_UPDATE_DT); //for Roll PID pidInit(&ctrl->pidX, 0, PID_X_KP, PID_X_KI, PID_X_KD, CAMERA_UPDATE_DT); //for Pitch PID pidInit(&ctrl->pidYaw, 0, PID_YAW_KP, PID_YAW_KI, PID_YAW_KD, CAMERA_UPDATE_DT); pidInit(&ctrl->pidZ, 0, PID_Z_KP, PID_Z_KI, PID_Z_KD, CAMERA_UPDATE_DT); pidSetIntegralLimit(&ctrl->pidY, PID_Y_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidX, PID_X_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidYaw, PID_YAW_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidZ, PID_Z_INTEGRATION_LIMIT); ctrl->isInit = true; } </pre> </code> </blockquote> '''Note:''' If we have multiple Crazyflies we need a <code>ControllerObject</code> for each Crazyflie (code in ''eris_vrpn.cpp'') <blockquote> <code> <pre> controllerResetAllPID( &pidCtrl1 ); controllerInit( &pidCtrl1 ); #endif #if NUM_QUADS >= 2 controllerResetAllPID( &pidCtrl2 ); controllerInit( &pidCtrl2 ); #endif #if NUM_QUADS >=3 controllerResetAllPID( &pidCtrl3 ); controllerInit( &pidCtrl3 ); #endif #if NUM_QUADS >=4 controllerResetAllPID( &pidCtrl4 ); controllerInit( &pidCtrl4 ); #endif </pre> </code> </blockquote> Now the initialization of the Controllers is complete. ====Calculating the PID's==== :1. Each loop we want to calculate the PID output (code in ''pid.c''): <blockquote> <code> <pre> float pidUpdateAngle(PidObject* pid, const float measured, const bool updateError) //**USED FOR ATTITUDE CONTROL { float output; if(updateError) { pid->error = pid->desired - measured; //Calculates current error } pid->integ += pid->error * pid->dt; //Calculates integral term if(pid->integ > pid->iLimit) //Checks that the integral term stays below the integral limit (anti-windup) { pid->integ = pid->iLimit; } else if(pid->integ < pid->iLimitLow) { pid->integ = pid->iLimitLow; } pid->deriv = (pid->error - pid->prevError) / pid->dt; //Calculates derivative term pid->outP = pid->kp* pid->error; pid->outI = pid->ki * pid->integ; pid->outD = pid->kd * pid->deriv; output = pid->outP + pid->outI + pid->outD; //Adds up all 3 calculated terms for output if(output > pid->angularLimit) //Limits amount Crazyflie can tip { output = pid->angularLimit; } if(output < pid->angularLimitLow) //Limits amount Crazyflie can tip { output = pid->angularLimitLow; } pid->prevError = pid->error; //Stores the current error for next loop return output; } </pre> </code> </blockquote> ::'''Note:''' There are 3 different versions of this Function (for Angle, Thrust, and Yaw) since each has different output limits. :2. Using the function above, combine all PID calculations into one function (code in ''controller.c''): <blockquote> <code> <pre> void controllerCorrectAttitudePID(ControllerObject * ctrl, float xPositionActual, float yPositionActual, float zPositionActual, float eulerYawActual, float xPositionDesired, float yPositionDesired, float zPositionDesired, float eulerYawDesired, float* rollControlOutput, float* pitchControlOutput, float* yawControlOutput, float* thrustControlOutput) { pidSetDesired(&ctrl->pidX, xPositionDesired); *pitchControlOutput = pidUpdateAngle(&ctrl->pidX, xPositionActual, false); //Originally true pidSetDesired(&ctrl->pidY, yPositionDesired); *rollControlOutput = pidUpdateAngle(&ctrl->pidY, yPositionActual, false); //Originally true pidSetDesired(&ctrl->pidZ, zPositionDesired); *thrustControlOutput = pidUpdateThrust(&ctrl->pidZ,zPositionActual, true); float yawError; pidSetDesired(&ctrl->pidYaw, eulerYawDesired); yawError = eulerYawDesired - eulerYawActual; if(yawError > 180.0) //Ensures Yaw error stays between -180 and 180 degrees yawError -= 360.0; else if(yawError < -180.0) yawError += 360.0; pidSetError(&ctrl->pidYaw, yawError); *yawControlOutput = pidUpdateYaw(&ctrl->pidYaw, eulerYawActual, true); //originally false } </pre> </code> </blockquote> :3. In each Callback, calculate the Controller outputs, assigned to pointer values <code>*rollControlOutput</code>, <code>*pitchControlOutput</code>, etc... (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; //Calculates error externally controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); </pre> </code> </blockquote> ::'''Note 1:''' We calculate error externally for X and Y because certain swarm controllers need special setpoint modifiers (this way we can switch modes without effecting the default setpoint): ::'''Note 2:''' Swap out the Controller - all we need to do is create a similar function and replace ''controllerCorrectAttitudePID'' above ::'''Example:''' Follow Hand Mode Error (Crazyflie1 will have setpoint -0.5 m lower in X and +0.5 m higher in Y than your hand trackable): <blockquote> <code> <pre> ... xError1 = (xPositionHand - 0.5) - xPosition1; yError1 = (yPositionHand + 0.5) - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); ... </pre> </code> </blockquote> :4. Send Calculated Control Outputs to the Crazyflie via the Radio (code found in ''simple.cpp''): <blockquote> <code> <pre> RunCrazyflie(crRadio2, cflieCopter3, rollControlOutput3, pitchControlOutput3, yawControlOutput3, thrustControlOutput3); </pre> </code> </blockquote> ::Where the ''RunCrazyflie'' function looks like this (code in ''simple.cpp''): <blockquote> <code> <pre> int RunCrazyflie(CCrazyRadio *crRadio, CCrazyflie *cflieCopter, float rollControl, float pitchControl, float yawControl, float thrustControl) { //Timing Index Variables (**FOR TESTING ROUTINES**) int i = 0; while(cflieCopter->cycle()) { //If Crazyflie is vertical kill motors, Crash Imminent if(cflieCopter->roll() > 90){ cflieCopter->setThrust(10000); } else if(cflieCopter->roll() < -90){ cflieCopter->setThrust(10000); } else if(cflieCopter->pitch() > 90){ cflieCopter->setThrust(10000); } else if(cflieCopter->pitch() < -90){ cflieCopter->setThrust(10000); } //Otherwise Send Setpoints else if(i < 1){ //i < 200000 cflieCopter->setThrust(thrustControl); cflieCopter->setRoll(rollControl); cflieCopter->setPitch(pitchControl); cflieCopter->setYaw(-yawControl); //******SET TO NEGATIVE FOR CAMERA SYSTEM YAW BEING REVERSED!!!!**** i++; } else{ break; } } return 0; } </pre> </code> </blockquote> ::'''IMPORTANT:''' This function contains the function <code>cflieCopter->cycle()</code> which is CRITICAL to maintaining communications with the Crazyflie. The ''cycle'' function initiates communications, sends setpoints, and must be called frequently otherwise the communications will timeout and the Crazyflie will stop as a precaution. :5. Repeat steps 3 through 5 for each set of new location data...until Program END. ===Swapping Client Controller Type=== With the Swarm Platform we can plug any controller (that can be coded in C or C++) into the Client to control the Crazyflies. In steps 1, 2, and 3 of the [[#Calculating the PID's|Calculating the PID's]] section, you can see the whole process of how we calculate the control output. To replace the PID with a different controller we can follow those steps but with our new controller. So as a general idea of the process we have: ('''Note:''' This depends heavily on how your controller works, this is generalized for a single input single output controller) #Implement the New Controller Output Calculation in C as a function #Create multiple instances of this controller calculation function (for each Degree of Freedom (DOF) you need to control) and combine them into a function to calculate all controllers with 1 function call ('''Note:''' This step is for ease of code use, NOT Required) #In each Callback, call the function to Calculate the Controller output. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> cf76160409329e16e2c8389086c915e325131b3d Logging 0 39 232 117 2016-08-02T18:55:19Z Jnoronha 3 /* MATLAB Parser */ added data import and x and y positions wikitext text/x-wiki The logging system is the most important analysis tool we have. This allows us to export any variable data we want out to an external text file. This way we can use any data processor to parse the data. (Excel, MATLAB, R, etc.) ==Client-Side External Log Files== We first need to initialize the log files and prepare them before each test. :1. Create empty File Pointers (code in 'eris_vrpn.cpp') <blockquote> <code> <pre> FILE * outHand = NULL; FILE * out1 = NULL; FILE * out2 = NULL; FILE * out3 = NULL; FILE * out4 = NULL; </pre> </code> </blockquote> :2. Make sure Logging is Enabled (and Basic Logging if desired) <blockquote> <code> <pre> #define USE_VRPN 1 #define USE_KEYBOARD 1 #define USE_PRINTOUT 0 #define USE_LOGGING 1 <---//Enables Full Logging #define USE_BASIC_LOGGING 1 <---//Only logs the necessities (FULL LOGGING MUST BE ENABLED FOR THIS TO WORK) #define USE_PR_YAW_CORRECT 0 #define USE_HAND 1 </pre> </code> </blockquote> :3. Create Log File Header (# = Log File Title, % = List of Variable Names, & = List of Variable Units) ::'''Note 1:''' This example is using BASIC_LOGGING 1, ::'''Note 2:''' Variables and units are separated by a double tab '\t\t' (Does not have to be '\t\t' any delimiter works) <blockquote> <code> <pre> const char * logHeaderHand = "#Hand Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tLoopTime\t\tLoopTimeDelta\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tseconds\t\tseconds\n"; const char * logHeader1 = "#Crazyflie1 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\t\tRadioRSSI\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\t\tstrength\n"; const char * logHeader2 = "#Crazyflie2 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader3 = "#Crazyflie3 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader4 = "#Crazyflie4 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; </pre> </code> </blockquote> :4. Open External .txt file and Print Header into file <blockquote> <code> <pre> #if USE_HAND outHand = fopen("hand.txt", "w"); //Opens text file with write permission if(outHand == NULL) { printf("Could not open hand.log: errno %d\n", errno); exit(-1); } fprintf(outHand, "%s\n", logHeaderHand); //Prints log header into corresponding file #endif if(cflieCopter1) //Checks to see if cflieCopter pointer has been initialized before opening file { out1 = fopen("cflie1.txt", "w"); if(out1 == NULL) { printf("Could not open cflie1.log: errno %d\n", errno); exit(-1); } fprintf(out1, "%s\n", logHeader1); } if(cflieCopter2) { out2 = fopen("cflie2.txt", "w"); if(out2 == NULL) { printf("Could not open cflie2.log:errno %d\n", errno); exit(-1); } fprintf(out2, "%s\n", logHeader2); } if(cflieCopter3) { out3 = fopen("cflie3.txt", "w"); if(out3 == NULL) { printf("Could not open cflie3.log:errno %d\n", errno); exit(-1); } fprintf(out3, "%s\n", logHeader3); } if(cflieCopter4) { out4 = fopen("cflie4.txt", "w"); if(out4 == NULL) { printf("Could not open cflie4.log:errno %d\n", errno); exit(-1); } fprintf(out4, "%s\n", logHeader4); } </pre> </code> </blockquote> :5. Init has Completed (Start Program Loop) Prints Variable values to file... ::'''Note 1:''' This code is run at the end of the Callback for each Crazyflie initialized (Executes once per new data packet) ::'''Note 2:''' This example is using BASIC_LOGGING, and is only showing Crazyflie1's code. <blockquote> <code> <pre> fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); fprintf(out1, "\n"); </pre> </code> </blockquote> :6. Close External .txt files before ending program <blockquote> <code> <pre> #if USE_LOGGING #if USE_HAND fclose(outHand); #endif #if NUM_QUADS >= 1 fclose(out1); #endif #if NUM_QUADS >= 2 fclose(out2); #endif #if NUM_QUADS >= 3 fclose(out3); #endif #if NUM_QUADS >= 4 fclose(out4); #endif #endif </pre> </code> </blockquote> ==MATLAB Parser== '''(**TODO**)''' We use a Matlab script to parse the log files. ===Multi-Logfile Parser=== The primary way we use to visualize the log files is via a very simple and messy MATLAB script. It consists of a bunch of sub-routines that were all thrown together into a single .m file. ====Import Log Data==== <blockquote> <code> <pre> %% Crazyflie Logging Parser [handLog, delimHand] = importdata('hand.txt','\t'); %Imports data from all 5 log files from the Swarm Client [cflie1Log, delim1] = importdata('cflie1.txt','\t'); [cflie2Log, delim2] = importdata('cflie2.txt','\t'); [cflie3Log, delim3] = importdata('cflie3.txt','\t'); [cflie4Log, delim4] = importdata('cflie4.txt','\t'); % handTime = handLog.data(:,1); handRoll = handLog.data(:,3); handPitch = handLog.data(:,5); handYaw = handLog.data(:,7); handX = handLog.data(:,9); %Assigns Hand Data to user-friendly variable names handY = handLog.data(:,11); handZ = handLog.data(:,13); handLoopTime = handLog.data(:,15); handLoopTimeDelta = handLog.data(:,17); % cflie1Time = cflie1Log.data(:,1); cflie1Roll = cflie1Log.data(:,3); cflie1Pitch = cflie1Log.data(:,5); %Assigns Crazyflie1 Data to user-friendly variable names cflie1Yaw = cflie1Log.data(:,7); cflie1X = cflie1Log.data(:,9); cflie1Y = cflie1Log.data(:,11); cflie1Z = cflie1Log.data(:,13); cflie1CamYaw = cflie1Log.data(:,15); cflie1CorrectedYaw = cflie1Log.data(:,17); cflie1LoopTimeTotal = cflie1Log.data(:,19); cflie1LoopTimeTotalDelta = cflie1Log.data(:,21); cflie1LoopTime = cflie1Log.data(:,23); cflie1LoopTimeDelta = cflie1Log.data(:,25); cflie1VrpnPacketDelta = cflie1Log.data(:,27); cflie1VrpnPacketTime = cflie1Log.data(:,29); cflie1VrpnPacketBackup = cflie1Log.data(:,31); % cflie1XSetpoint = cflie1Log.data(:,33); % cflie1YSetpoint = cflie1Log.data(:,35); % cflie1ZSetpoint = cflie1Log.data(:,37); % cflie1YawSetpoint = cflie1Log.data(:,39); % cflie1PitchDesired = cflie1Log.data(:,41); % cflie1RollDesired = cflie1Log.data(:,43); % cflie1YawDesired = cflie1Log.data(:,45); % cflie1ThrustDesired = cflie1Log.data(:,47); % cflie1RadioRSSI = cflie1Log.data(:,49); % cflie1CamYawRad = cflie1Log.data(:,51); % cflie1CamPitchRad = cflie1Log.data(:,53); % cflie1CamRollRad = cflie1Log.data(:,55); % cflie1Motor1 = cflie1Log.data(:,57); % cflie1Motor2 = cflie1Log.data(:,59); % cflie1Motor3 = cflie1Log.data(:,61); % cflie1Motor4 = cflie1Log.data(:,63); % cflie1RollRate = cflie1Log.data(:,65); % cflie1PitchRate = cflie1Log.data(:,67); % cflie1YawRate = cflie1Log.data(:,69); ... ... ... (same for Crazyflie 2, 3, and 4..) ... ... </pre> </code> </blockquote> ::'''Note:''' This list needs to match the log file length that the Swarm Client creates (comment out as needed) ====Plotting X and Y Position of Crazyflies==== <blockquote> <code> <pre> %% Plot X Using ImportData figure(8) %Plotting X-Positions hold off plot(cflie1Time,cflie1X, '-b') hold on % plot(cflie1Time,cflie1XSetpoint, '-.b') % plot(cflie2Time,cflie2X, '-g') % plot(cflie2Time,cflie2XSetpoint, '-.g') % plot(cflie3Time,cflie3X, '-k') % plot(cflie3Time,cflie3XSetpoint, '-.k') % plot(cflie4Time,cflie4X, '-y') % plot(handTime, handX, '-r') % plot(cflie4Time,cflie4XSetpoint, '-.y') title 'Crazyflie X-Positions' legend('Crazyflie 1','Crazyflie 2','Crazyflie3', 'Crazyflie4', 'Hand') xlabel 'Time (seconds)' ylabel 'X-Position (m)' grid on % legend('Crazyflie 1','Setpoint', 'Crazyflie 2','Setpoint', 'Crazyflie3','Setpoint', 'Crazyflie4','Setpoint') % % figure(9) %Plotting Y-Positions hold off plot(cflie1Time,cflie1Y, '-b') hold on % plot(cflie1Time,cflie1YSetpoint, '-.b') % plot(cflie2Time,cflie2Y, '-g') % plot(cflie2Time,cflie2YSetpoint, '-.g') % plot(cflie3Time,cflie3Y, '-k') % plot(cflie3Time,cflie3YSetpoint, '-.k') % plot(cflie4Time,cflie4Y, '-y') % plot(cflie3Time,cflie3YSetpoint, '-.y') % plot(handTime, handY, '-r') title 'Crazyflie Y-Positions' legend('Crazyflie 1','Crazyflie 2','Crazyflie3', 'Crazyflie4', 'Hand') % legend('Crazyflie 1', 'Setpoint','Crazyflie 2', 'Setpoint','Crazyflie3','Setpoint', 'Crazyflie4','Setpoint') xlabel 'Time (seconds)' ylabel 'Y-Position (m)' grid on </pre> </code> </blockquote> ===[http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool Universal Lab Parser (Alternative)]=== Alternatively, the lab has a unified logging format that can be read by a universal log parser. More information about this parsing method [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool can be found here] The Swarm Platform log files are compatible with this format and can be used just as any other lab log files. The problem is that this parser can '''only view a single text file at a time'''. This makes comparisons and plotting across all Crazyflies in the swarm very very difficult. ==New Client Log Blocks== In the Swarm Client there is a sub-system designed for creating and maintaining Log Blocks. Once you have [[:Firmware#Log Blocks|created a new log block in the Firmware]] that you want to utilize we can do the following: :1. Create an Enable function for the New Log Block (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::enableMagnetometerLogging() { m_tocLogs->registerLoggingBlock("magnetometer", 1000); m_tocLogs->startLogging("mag.x", "magnetometer"); m_tocLogs->startLogging("mag.y", "magnetometer"); m_tocLogs->startLogging("mag.z", "magnetometer"); } </pre> </code> </blockquote> ::This will then register a log block called ''magnetometer'' on the Client, which will be updated every 1000 &mu;s. It will then update the values listed in the block (X, Y, Z of the magnetometer). ::'''Note 1:''' The ''"mag.x"'' term must match the name defined in the Firmware log block (see [[:Firmware#Log Blocks|firmware example 1]]) ::'''Note 2:''' The 2nd input to the ''startLogging'' function needs to match the name of the Client Log block we registered (in this case ''"magnetometer"'') :2. Add the ''enableLogBlock'' function we just made to the list of Log blocks we want at startup (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::startLogging() { // Register the desired sensor readings this->enableStabilizerLogging(); // this->enableGyroscopeLogging(); // this->enableAccelerometerLogging(); this->enableBatteryLogging(); this->enableMagnetometerLogging(); <-----//This is the one we just made // this->enableAltimeterLogging(); // this->enablePIDOutputLogging(); // this->enableRadioRSSILogging(); // this->enableMotorLogging(); return true; } </pre> </code> </blockquote> ::This ''startLogging'' function runs during Crazyflie startup and will start all the log blocks listed. As you can see we have some log blocks commented out currently so that we do NOT start those blocks. :3. Create Functions to Read the variable values during runtime (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> float CCrazyflie::magX() { return this->sensorDoubleValue("mag.x"); } float CCrazyflie::magY() { return this->sensorDoubleValue("mag.y"); } float CCrazyflie::magZ() { return this->sensorDoubleValue("mag.z"); } </pre> </code> </blockquote> ::So now we can use these sensor values, from the Firmware, in the Client code with <code>magX1 = cflieCopter1->magX()</code>. This will store the sensor value in the Client-side variable ''magX1''. :4. (OPTIONAL) We can also create a function to stop logging an individual log block in the Client (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::disableMagnetometerLogging() { m_tocLogs->unregisterLoggingBlock("magnetometer"); } </pre> </code> </blockquote> ::This is straightforward, it just tells the client to stop logging this block. :5. (OPTIONAL) And we can stop ALL log blocks in the client as well (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::stopLogging() { this->disableStabilizerLogging(); this->disableGyroscopeLogging(); this->disableAccelerometerLogging(); this->disableBatteryLogging(); // this->disableMagnetometerLogging(); // this->disableAltimeterLogging(); // this->disablePIDOutputLogging(); this->disableRadioRSSILogging(); this->disableMotorLogging(); return true; } </pre> </code> </blockquote> ::This will disable ALL the logging blocks included in the list. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 720bf5dc37b42ee104353cd69a0df6294642ad6d 233 232 2016-08-02T19:00:24Z Jnoronha 3 moved the matlab section to the bottom wikitext text/x-wiki The logging system is the most important analysis tool we have. This allows us to export any variable data we want out to an external text file. This way we can use any data processor to parse the data. (Excel, MATLAB, R, etc.) ==Client-Side External Log Files== We first need to initialize the log files and prepare them before each test. :1. Create empty File Pointers (code in 'eris_vrpn.cpp') <blockquote> <code> <pre> FILE * outHand = NULL; FILE * out1 = NULL; FILE * out2 = NULL; FILE * out3 = NULL; FILE * out4 = NULL; </pre> </code> </blockquote> :2. Make sure Logging is Enabled (and Basic Logging if desired) <blockquote> <code> <pre> #define USE_VRPN 1 #define USE_KEYBOARD 1 #define USE_PRINTOUT 0 #define USE_LOGGING 1 <---//Enables Full Logging #define USE_BASIC_LOGGING 1 <---//Only logs the necessities (FULL LOGGING MUST BE ENABLED FOR THIS TO WORK) #define USE_PR_YAW_CORRECT 0 #define USE_HAND 1 </pre> </code> </blockquote> :3. Create Log File Header (# = Log File Title, % = List of Variable Names, & = List of Variable Units) ::'''Note 1:''' This example is using BASIC_LOGGING 1, ::'''Note 2:''' Variables and units are separated by a double tab '\t\t' (Does not have to be '\t\t' any delimiter works) <blockquote> <code> <pre> const char * logHeaderHand = "#Hand Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tLoopTime\t\tLoopTimeDelta\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tseconds\t\tseconds\n"; const char * logHeader1 = "#Crazyflie1 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\t\tRadioRSSI\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\t\tstrength\n"; const char * logHeader2 = "#Crazyflie2 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader3 = "#Crazyflie3 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader4 = "#Crazyflie4 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; </pre> </code> </blockquote> :4. Open External .txt file and Print Header into file <blockquote> <code> <pre> #if USE_HAND outHand = fopen("hand.txt", "w"); //Opens text file with write permission if(outHand == NULL) { printf("Could not open hand.log: errno %d\n", errno); exit(-1); } fprintf(outHand, "%s\n", logHeaderHand); //Prints log header into corresponding file #endif if(cflieCopter1) //Checks to see if cflieCopter pointer has been initialized before opening file { out1 = fopen("cflie1.txt", "w"); if(out1 == NULL) { printf("Could not open cflie1.log: errno %d\n", errno); exit(-1); } fprintf(out1, "%s\n", logHeader1); } if(cflieCopter2) { out2 = fopen("cflie2.txt", "w"); if(out2 == NULL) { printf("Could not open cflie2.log:errno %d\n", errno); exit(-1); } fprintf(out2, "%s\n", logHeader2); } if(cflieCopter3) { out3 = fopen("cflie3.txt", "w"); if(out3 == NULL) { printf("Could not open cflie3.log:errno %d\n", errno); exit(-1); } fprintf(out3, "%s\n", logHeader3); } if(cflieCopter4) { out4 = fopen("cflie4.txt", "w"); if(out4 == NULL) { printf("Could not open cflie4.log:errno %d\n", errno); exit(-1); } fprintf(out4, "%s\n", logHeader4); } </pre> </code> </blockquote> :5. Init has Completed (Start Program Loop) Prints Variable values to file... ::'''Note 1:''' This code is run at the end of the Callback for each Crazyflie initialized (Executes once per new data packet) ::'''Note 2:''' This example is using BASIC_LOGGING, and is only showing Crazyflie1's code. <blockquote> <code> <pre> fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); fprintf(out1, "\n"); </pre> </code> </blockquote> :6. Close External .txt files before ending program <blockquote> <code> <pre> #if USE_LOGGING #if USE_HAND fclose(outHand); #endif #if NUM_QUADS >= 1 fclose(out1); #endif #if NUM_QUADS >= 2 fclose(out2); #endif #if NUM_QUADS >= 3 fclose(out3); #endif #if NUM_QUADS >= 4 fclose(out4); #endif #endif </pre> </code> </blockquote> ===[http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool Universal Lab Parser (Alternative)]=== Alternatively, the lab has a unified logging format that can be read by a universal log parser. More information about this parsing method [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool can be found here] The Swarm Platform log files are compatible with this format and can be used just as any other lab log files. The problem is that this parser can '''only view a single text file at a time'''. This makes comparisons and plotting across all Crazyflies in the swarm very very difficult. ==New Client Log Blocks== In the Swarm Client there is a sub-system designed for creating and maintaining Log Blocks. Once you have [[:Firmware#Log Blocks|created a new log block in the Firmware]] that you want to utilize we can do the following: :1. Create an Enable function for the New Log Block (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::enableMagnetometerLogging() { m_tocLogs->registerLoggingBlock("magnetometer", 1000); m_tocLogs->startLogging("mag.x", "magnetometer"); m_tocLogs->startLogging("mag.y", "magnetometer"); m_tocLogs->startLogging("mag.z", "magnetometer"); } </pre> </code> </blockquote> ::This will then register a log block called ''magnetometer'' on the Client, which will be updated every 1000 &mu;s. It will then update the values listed in the block (X, Y, Z of the magnetometer). ::'''Note 1:''' The ''"mag.x"'' term must match the name defined in the Firmware log block (see [[:Firmware#Log Blocks|firmware example 1]]) ::'''Note 2:''' The 2nd input to the ''startLogging'' function needs to match the name of the Client Log block we registered (in this case ''"magnetometer"'') :2. Add the ''enableLogBlock'' function we just made to the list of Log blocks we want at startup (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::startLogging() { // Register the desired sensor readings this->enableStabilizerLogging(); // this->enableGyroscopeLogging(); // this->enableAccelerometerLogging(); this->enableBatteryLogging(); this->enableMagnetometerLogging(); <-----//This is the one we just made // this->enableAltimeterLogging(); // this->enablePIDOutputLogging(); // this->enableRadioRSSILogging(); // this->enableMotorLogging(); return true; } </pre> </code> </blockquote> ::This ''startLogging'' function runs during Crazyflie startup and will start all the log blocks listed. As you can see we have some log blocks commented out currently so that we do NOT start those blocks. :3. Create Functions to Read the variable values during runtime (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> float CCrazyflie::magX() { return this->sensorDoubleValue("mag.x"); } float CCrazyflie::magY() { return this->sensorDoubleValue("mag.y"); } float CCrazyflie::magZ() { return this->sensorDoubleValue("mag.z"); } </pre> </code> </blockquote> ::So now we can use these sensor values, from the Firmware, in the Client code with <code>magX1 = cflieCopter1->magX()</code>. This will store the sensor value in the Client-side variable ''magX1''. :4. (OPTIONAL) We can also create a function to stop logging an individual log block in the Client (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::disableMagnetometerLogging() { m_tocLogs->unregisterLoggingBlock("magnetometer"); } </pre> </code> </blockquote> ::This is straightforward, it just tells the client to stop logging this block. :5. (OPTIONAL) And we can stop ALL log blocks in the client as well (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::stopLogging() { this->disableStabilizerLogging(); this->disableGyroscopeLogging(); this->disableAccelerometerLogging(); this->disableBatteryLogging(); // this->disableMagnetometerLogging(); // this->disableAltimeterLogging(); // this->disablePIDOutputLogging(); this->disableRadioRSSILogging(); this->disableMotorLogging(); return true; } </pre> </code> </blockquote> ::This will disable ALL the logging blocks included in the list. ==MATLAB Parser== '''(**TODO**)''' We use a Matlab script to parse the log files. ===Multi-Logfile Parser=== The primary way we use to visualize the log files is via a very simple and messy MATLAB script. It consists of a bunch of sub-routines that were all thrown together into a single .m file. ====Import Log Data==== <blockquote> <code> <pre> %% Crazyflie Logging Parser [handLog, delimHand] = importdata('hand.txt','\t'); %Imports data from all 5 log files from the Swarm Client [cflie1Log, delim1] = importdata('cflie1.txt','\t'); [cflie2Log, delim2] = importdata('cflie2.txt','\t'); [cflie3Log, delim3] = importdata('cflie3.txt','\t'); [cflie4Log, delim4] = importdata('cflie4.txt','\t'); % handTime = handLog.data(:,1); handRoll = handLog.data(:,3); handPitch = handLog.data(:,5); handYaw = handLog.data(:,7); handX = handLog.data(:,9); %Assigns Hand Data to user-friendly variable names handY = handLog.data(:,11); handZ = handLog.data(:,13); handLoopTime = handLog.data(:,15); handLoopTimeDelta = handLog.data(:,17); % cflie1Time = cflie1Log.data(:,1); cflie1Roll = cflie1Log.data(:,3); cflie1Pitch = cflie1Log.data(:,5); %Assigns Crazyflie1 Data to user-friendly variable names cflie1Yaw = cflie1Log.data(:,7); cflie1X = cflie1Log.data(:,9); cflie1Y = cflie1Log.data(:,11); cflie1Z = cflie1Log.data(:,13); cflie1CamYaw = cflie1Log.data(:,15); cflie1CorrectedYaw = cflie1Log.data(:,17); cflie1LoopTimeTotal = cflie1Log.data(:,19); cflie1LoopTimeTotalDelta = cflie1Log.data(:,21); cflie1LoopTime = cflie1Log.data(:,23); cflie1LoopTimeDelta = cflie1Log.data(:,25); cflie1VrpnPacketDelta = cflie1Log.data(:,27); cflie1VrpnPacketTime = cflie1Log.data(:,29); cflie1VrpnPacketBackup = cflie1Log.data(:,31); % cflie1XSetpoint = cflie1Log.data(:,33); % cflie1YSetpoint = cflie1Log.data(:,35); % cflie1ZSetpoint = cflie1Log.data(:,37); % cflie1YawSetpoint = cflie1Log.data(:,39); % cflie1PitchDesired = cflie1Log.data(:,41); % cflie1RollDesired = cflie1Log.data(:,43); % cflie1YawDesired = cflie1Log.data(:,45); % cflie1ThrustDesired = cflie1Log.data(:,47); % cflie1RadioRSSI = cflie1Log.data(:,49); % cflie1CamYawRad = cflie1Log.data(:,51); % cflie1CamPitchRad = cflie1Log.data(:,53); % cflie1CamRollRad = cflie1Log.data(:,55); % cflie1Motor1 = cflie1Log.data(:,57); % cflie1Motor2 = cflie1Log.data(:,59); % cflie1Motor3 = cflie1Log.data(:,61); % cflie1Motor4 = cflie1Log.data(:,63); % cflie1RollRate = cflie1Log.data(:,65); % cflie1PitchRate = cflie1Log.data(:,67); % cflie1YawRate = cflie1Log.data(:,69); ... ... ... (same for Crazyflie 2, 3, and 4..) ... ... </pre> </code> </blockquote> ::'''Note:''' This list needs to match the log file length that the Swarm Client creates (comment out as needed) ====Plotting X and Y Position of Crazyflies==== <blockquote> <code> <pre> %% Plot X Using ImportData figure(8) %Plotting X-Positions hold off plot(cflie1Time,cflie1X, '-b') hold on % plot(cflie1Time,cflie1XSetpoint, '-.b') % plot(cflie2Time,cflie2X, '-g') % plot(cflie2Time,cflie2XSetpoint, '-.g') % plot(cflie3Time,cflie3X, '-k') % plot(cflie3Time,cflie3XSetpoint, '-.k') % plot(cflie4Time,cflie4X, '-y') % plot(handTime, handX, '-r') % plot(cflie4Time,cflie4XSetpoint, '-.y') title 'Crazyflie X-Positions' legend('Crazyflie 1','Crazyflie 2','Crazyflie3', 'Crazyflie4', 'Hand') xlabel 'Time (seconds)' ylabel 'X-Position (m)' grid on % legend('Crazyflie 1','Setpoint', 'Crazyflie 2','Setpoint', 'Crazyflie3','Setpoint', 'Crazyflie4','Setpoint') % % figure(9) %Plotting Y-Positions hold off plot(cflie1Time,cflie1Y, '-b') hold on % plot(cflie1Time,cflie1YSetpoint, '-.b') % plot(cflie2Time,cflie2Y, '-g') % plot(cflie2Time,cflie2YSetpoint, '-.g') % plot(cflie3Time,cflie3Y, '-k') % plot(cflie3Time,cflie3YSetpoint, '-.k') % plot(cflie4Time,cflie4Y, '-y') % plot(cflie3Time,cflie3YSetpoint, '-.y') % plot(handTime, handY, '-r') title 'Crazyflie Y-Positions' legend('Crazyflie 1','Crazyflie 2','Crazyflie3', 'Crazyflie4', 'Hand') % legend('Crazyflie 1', 'Setpoint','Crazyflie 2', 'Setpoint','Crazyflie3','Setpoint', 'Crazyflie4','Setpoint') xlabel 'Time (seconds)' ylabel 'Y-Position (m)' grid on </pre> </code> </blockquote> ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 09f13122bea10e3a9d412fa98ba333701d2e6708 234 233 2016-08-02T19:01:47Z Jnoronha 3 forgot to move the universal parser also wikitext text/x-wiki The logging system is the most important analysis tool we have. This allows us to export any variable data we want out to an external text file. This way we can use any data processor to parse the data. (Excel, MATLAB, R, etc.) ==Client-Side External Log Files== We first need to initialize the log files and prepare them before each test. :1. Create empty File Pointers (code in 'eris_vrpn.cpp') <blockquote> <code> <pre> FILE * outHand = NULL; FILE * out1 = NULL; FILE * out2 = NULL; FILE * out3 = NULL; FILE * out4 = NULL; </pre> </code> </blockquote> :2. Make sure Logging is Enabled (and Basic Logging if desired) <blockquote> <code> <pre> #define USE_VRPN 1 #define USE_KEYBOARD 1 #define USE_PRINTOUT 0 #define USE_LOGGING 1 <---//Enables Full Logging #define USE_BASIC_LOGGING 1 <---//Only logs the necessities (FULL LOGGING MUST BE ENABLED FOR THIS TO WORK) #define USE_PR_YAW_CORRECT 0 #define USE_HAND 1 </pre> </code> </blockquote> :3. Create Log File Header (# = Log File Title, % = List of Variable Names, & = List of Variable Units) ::'''Note 1:''' This example is using BASIC_LOGGING 1, ::'''Note 2:''' Variables and units are separated by a double tab '\t\t' (Does not have to be '\t\t' any delimiter works) <blockquote> <code> <pre> const char * logHeaderHand = "#Hand Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tLoopTime\t\tLoopTimeDelta\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tseconds\t\tseconds\n"; const char * logHeader1 = "#Crazyflie1 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\t\tRadioRSSI\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\t\tstrength\n"; const char * logHeader2 = "#Crazyflie2 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader3 = "#Crazyflie3 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader4 = "#Crazyflie4 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; </pre> </code> </blockquote> :4. Open External .txt file and Print Header into file <blockquote> <code> <pre> #if USE_HAND outHand = fopen("hand.txt", "w"); //Opens text file with write permission if(outHand == NULL) { printf("Could not open hand.log: errno %d\n", errno); exit(-1); } fprintf(outHand, "%s\n", logHeaderHand); //Prints log header into corresponding file #endif if(cflieCopter1) //Checks to see if cflieCopter pointer has been initialized before opening file { out1 = fopen("cflie1.txt", "w"); if(out1 == NULL) { printf("Could not open cflie1.log: errno %d\n", errno); exit(-1); } fprintf(out1, "%s\n", logHeader1); } if(cflieCopter2) { out2 = fopen("cflie2.txt", "w"); if(out2 == NULL) { printf("Could not open cflie2.log:errno %d\n", errno); exit(-1); } fprintf(out2, "%s\n", logHeader2); } if(cflieCopter3) { out3 = fopen("cflie3.txt", "w"); if(out3 == NULL) { printf("Could not open cflie3.log:errno %d\n", errno); exit(-1); } fprintf(out3, "%s\n", logHeader3); } if(cflieCopter4) { out4 = fopen("cflie4.txt", "w"); if(out4 == NULL) { printf("Could not open cflie4.log:errno %d\n", errno); exit(-1); } fprintf(out4, "%s\n", logHeader4); } </pre> </code> </blockquote> :5. Init has Completed (Start Program Loop) Prints Variable values to file... ::'''Note 1:''' This code is run at the end of the Callback for each Crazyflie initialized (Executes once per new data packet) ::'''Note 2:''' This example is using BASIC_LOGGING, and is only showing Crazyflie1's code. <blockquote> <code> <pre> fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); fprintf(out1, "\n"); </pre> </code> </blockquote> :6. Close External .txt files before ending program <blockquote> <code> <pre> #if USE_LOGGING #if USE_HAND fclose(outHand); #endif #if NUM_QUADS >= 1 fclose(out1); #endif #if NUM_QUADS >= 2 fclose(out2); #endif #if NUM_QUADS >= 3 fclose(out3); #endif #if NUM_QUADS >= 4 fclose(out4); #endif #endif </pre> </code> </blockquote> ==New Client Log Blocks== In the Swarm Client there is a sub-system designed for creating and maintaining Log Blocks. Once you have [[:Firmware#Log Blocks|created a new log block in the Firmware]] that you want to utilize we can do the following: :1. Create an Enable function for the New Log Block (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::enableMagnetometerLogging() { m_tocLogs->registerLoggingBlock("magnetometer", 1000); m_tocLogs->startLogging("mag.x", "magnetometer"); m_tocLogs->startLogging("mag.y", "magnetometer"); m_tocLogs->startLogging("mag.z", "magnetometer"); } </pre> </code> </blockquote> ::This will then register a log block called ''magnetometer'' on the Client, which will be updated every 1000 &mu;s. It will then update the values listed in the block (X, Y, Z of the magnetometer). ::'''Note 1:''' The ''"mag.x"'' term must match the name defined in the Firmware log block (see [[:Firmware#Log Blocks|firmware example 1]]) ::'''Note 2:''' The 2nd input to the ''startLogging'' function needs to match the name of the Client Log block we registered (in this case ''"magnetometer"'') :2. Add the ''enableLogBlock'' function we just made to the list of Log blocks we want at startup (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::startLogging() { // Register the desired sensor readings this->enableStabilizerLogging(); // this->enableGyroscopeLogging(); // this->enableAccelerometerLogging(); this->enableBatteryLogging(); this->enableMagnetometerLogging(); <-----//This is the one we just made // this->enableAltimeterLogging(); // this->enablePIDOutputLogging(); // this->enableRadioRSSILogging(); // this->enableMotorLogging(); return true; } </pre> </code> </blockquote> ::This ''startLogging'' function runs during Crazyflie startup and will start all the log blocks listed. As you can see we have some log blocks commented out currently so that we do NOT start those blocks. :3. Create Functions to Read the variable values during runtime (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> float CCrazyflie::magX() { return this->sensorDoubleValue("mag.x"); } float CCrazyflie::magY() { return this->sensorDoubleValue("mag.y"); } float CCrazyflie::magZ() { return this->sensorDoubleValue("mag.z"); } </pre> </code> </blockquote> ::So now we can use these sensor values, from the Firmware, in the Client code with <code>magX1 = cflieCopter1->magX()</code>. This will store the sensor value in the Client-side variable ''magX1''. :4. (OPTIONAL) We can also create a function to stop logging an individual log block in the Client (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::disableMagnetometerLogging() { m_tocLogs->unregisterLoggingBlock("magnetometer"); } </pre> </code> </blockquote> ::This is straightforward, it just tells the client to stop logging this block. :5. (OPTIONAL) And we can stop ALL log blocks in the client as well (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::stopLogging() { this->disableStabilizerLogging(); this->disableGyroscopeLogging(); this->disableAccelerometerLogging(); this->disableBatteryLogging(); // this->disableMagnetometerLogging(); // this->disableAltimeterLogging(); // this->disablePIDOutputLogging(); this->disableRadioRSSILogging(); this->disableMotorLogging(); return true; } </pre> </code> </blockquote> ::This will disable ALL the logging blocks included in the list. ==MATLAB Parser== '''(**TODO**)''' We use a Matlab script to parse the log files. ===Multi-Logfile Parser=== The primary way we use to visualize the log files is via a very simple and messy MATLAB script. It consists of a bunch of sub-routines that were all thrown together into a single .m file. ====Import Log Data==== <blockquote> <code> <pre> %% Crazyflie Logging Parser [handLog, delimHand] = importdata('hand.txt','\t'); %Imports data from all 5 log files from the Swarm Client [cflie1Log, delim1] = importdata('cflie1.txt','\t'); [cflie2Log, delim2] = importdata('cflie2.txt','\t'); [cflie3Log, delim3] = importdata('cflie3.txt','\t'); [cflie4Log, delim4] = importdata('cflie4.txt','\t'); % handTime = handLog.data(:,1); handRoll = handLog.data(:,3); handPitch = handLog.data(:,5); handYaw = handLog.data(:,7); handX = handLog.data(:,9); %Assigns Hand Data to user-friendly variable names handY = handLog.data(:,11); handZ = handLog.data(:,13); handLoopTime = handLog.data(:,15); handLoopTimeDelta = handLog.data(:,17); % cflie1Time = cflie1Log.data(:,1); cflie1Roll = cflie1Log.data(:,3); cflie1Pitch = cflie1Log.data(:,5); %Assigns Crazyflie1 Data to user-friendly variable names cflie1Yaw = cflie1Log.data(:,7); cflie1X = cflie1Log.data(:,9); cflie1Y = cflie1Log.data(:,11); cflie1Z = cflie1Log.data(:,13); cflie1CamYaw = cflie1Log.data(:,15); cflie1CorrectedYaw = cflie1Log.data(:,17); cflie1LoopTimeTotal = cflie1Log.data(:,19); cflie1LoopTimeTotalDelta = cflie1Log.data(:,21); cflie1LoopTime = cflie1Log.data(:,23); cflie1LoopTimeDelta = cflie1Log.data(:,25); cflie1VrpnPacketDelta = cflie1Log.data(:,27); cflie1VrpnPacketTime = cflie1Log.data(:,29); cflie1VrpnPacketBackup = cflie1Log.data(:,31); % cflie1XSetpoint = cflie1Log.data(:,33); % cflie1YSetpoint = cflie1Log.data(:,35); % cflie1ZSetpoint = cflie1Log.data(:,37); % cflie1YawSetpoint = cflie1Log.data(:,39); % cflie1PitchDesired = cflie1Log.data(:,41); % cflie1RollDesired = cflie1Log.data(:,43); % cflie1YawDesired = cflie1Log.data(:,45); % cflie1ThrustDesired = cflie1Log.data(:,47); % cflie1RadioRSSI = cflie1Log.data(:,49); % cflie1CamYawRad = cflie1Log.data(:,51); % cflie1CamPitchRad = cflie1Log.data(:,53); % cflie1CamRollRad = cflie1Log.data(:,55); % cflie1Motor1 = cflie1Log.data(:,57); % cflie1Motor2 = cflie1Log.data(:,59); % cflie1Motor3 = cflie1Log.data(:,61); % cflie1Motor4 = cflie1Log.data(:,63); % cflie1RollRate = cflie1Log.data(:,65); % cflie1PitchRate = cflie1Log.data(:,67); % cflie1YawRate = cflie1Log.data(:,69); ... ... ... (same for Crazyflie 2, 3, and 4..) ... ... </pre> </code> </blockquote> ::'''Note:''' This list needs to match the log file length that the Swarm Client creates (comment out as needed) ====Plotting X and Y Position of Crazyflies==== <blockquote> <code> <pre> %% Plot X Using ImportData figure(8) %Plotting X-Positions hold off plot(cflie1Time,cflie1X, '-b') hold on % plot(cflie1Time,cflie1XSetpoint, '-.b') % plot(cflie2Time,cflie2X, '-g') % plot(cflie2Time,cflie2XSetpoint, '-.g') % plot(cflie3Time,cflie3X, '-k') % plot(cflie3Time,cflie3XSetpoint, '-.k') % plot(cflie4Time,cflie4X, '-y') % plot(handTime, handX, '-r') % plot(cflie4Time,cflie4XSetpoint, '-.y') title 'Crazyflie X-Positions' legend('Crazyflie 1','Crazyflie 2','Crazyflie3', 'Crazyflie4', 'Hand') xlabel 'Time (seconds)' ylabel 'X-Position (m)' grid on % legend('Crazyflie 1','Setpoint', 'Crazyflie 2','Setpoint', 'Crazyflie3','Setpoint', 'Crazyflie4','Setpoint') % % figure(9) %Plotting Y-Positions hold off plot(cflie1Time,cflie1Y, '-b') hold on % plot(cflie1Time,cflie1YSetpoint, '-.b') % plot(cflie2Time,cflie2Y, '-g') % plot(cflie2Time,cflie2YSetpoint, '-.g') % plot(cflie3Time,cflie3Y, '-k') % plot(cflie3Time,cflie3YSetpoint, '-.k') % plot(cflie4Time,cflie4Y, '-y') % plot(cflie3Time,cflie3YSetpoint, '-.y') % plot(handTime, handY, '-r') title 'Crazyflie Y-Positions' legend('Crazyflie 1','Crazyflie 2','Crazyflie3', 'Crazyflie4', 'Hand') % legend('Crazyflie 1', 'Setpoint','Crazyflie 2', 'Setpoint','Crazyflie3','Setpoint', 'Crazyflie4','Setpoint') xlabel 'Time (seconds)' ylabel 'Y-Position (m)' grid on </pre> </code> </blockquote> ===[http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool Universal Lab Parser (Alternative)]=== Alternatively, the lab has a unified logging format that can be read by a universal log parser. More information about this parsing method [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool can be found here] The Swarm Platform log files are compatible with this format and can be used just as any other lab log files. The problem is that this parser can '''only view a single text file at a time'''. This makes comparisons and plotting across all Crazyflies in the swarm very very difficult. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 4da73c93ed2dd4ef436688937ad8869626b34e4f 240 234 2016-08-02T19:47:14Z Jnoronha 3 /* MATLAB Parser */ added figures and finished usable sections wikitext text/x-wiki The logging system is the most important analysis tool we have. This allows us to export any variable data we want out to an external text file. This way we can use any data processor to parse the data. (Excel, MATLAB, R, etc.) ==Client-Side External Log Files== We first need to initialize the log files and prepare them before each test. :1. Create empty File Pointers (code in 'eris_vrpn.cpp') <blockquote> <code> <pre> FILE * outHand = NULL; FILE * out1 = NULL; FILE * out2 = NULL; FILE * out3 = NULL; FILE * out4 = NULL; </pre> </code> </blockquote> :2. Make sure Logging is Enabled (and Basic Logging if desired) <blockquote> <code> <pre> #define USE_VRPN 1 #define USE_KEYBOARD 1 #define USE_PRINTOUT 0 #define USE_LOGGING 1 <---//Enables Full Logging #define USE_BASIC_LOGGING 1 <---//Only logs the necessities (FULL LOGGING MUST BE ENABLED FOR THIS TO WORK) #define USE_PR_YAW_CORRECT 0 #define USE_HAND 1 </pre> </code> </blockquote> :3. Create Log File Header (# = Log File Title, % = List of Variable Names, & = List of Variable Units) ::'''Note 1:''' This example is using BASIC_LOGGING 1, ::'''Note 2:''' Variables and units are separated by a double tab '\t\t' (Does not have to be '\t\t' any delimiter works) <blockquote> <code> <pre> const char * logHeaderHand = "#Hand Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tLoopTime\t\tLoopTimeDelta\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tseconds\t\tseconds\n"; const char * logHeader1 = "#Crazyflie1 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\t\tRadioRSSI\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\t\tstrength\n"; const char * logHeader2 = "#Crazyflie2 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader3 = "#Crazyflie3 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader4 = "#Crazyflie4 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; </pre> </code> </blockquote> :4. Open External .txt file and Print Header into file <blockquote> <code> <pre> #if USE_HAND outHand = fopen("hand.txt", "w"); //Opens text file with write permission if(outHand == NULL) { printf("Could not open hand.log: errno %d\n", errno); exit(-1); } fprintf(outHand, "%s\n", logHeaderHand); //Prints log header into corresponding file #endif if(cflieCopter1) //Checks to see if cflieCopter pointer has been initialized before opening file { out1 = fopen("cflie1.txt", "w"); if(out1 == NULL) { printf("Could not open cflie1.log: errno %d\n", errno); exit(-1); } fprintf(out1, "%s\n", logHeader1); } if(cflieCopter2) { out2 = fopen("cflie2.txt", "w"); if(out2 == NULL) { printf("Could not open cflie2.log:errno %d\n", errno); exit(-1); } fprintf(out2, "%s\n", logHeader2); } if(cflieCopter3) { out3 = fopen("cflie3.txt", "w"); if(out3 == NULL) { printf("Could not open cflie3.log:errno %d\n", errno); exit(-1); } fprintf(out3, "%s\n", logHeader3); } if(cflieCopter4) { out4 = fopen("cflie4.txt", "w"); if(out4 == NULL) { printf("Could not open cflie4.log:errno %d\n", errno); exit(-1); } fprintf(out4, "%s\n", logHeader4); } </pre> </code> </blockquote> :5. Init has Completed (Start Program Loop) Prints Variable values to file... ::'''Note 1:''' This code is run at the end of the Callback for each Crazyflie initialized (Executes once per new data packet) ::'''Note 2:''' This example is using BASIC_LOGGING, and is only showing Crazyflie1's code. <blockquote> <code> <pre> fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); fprintf(out1, "\n"); </pre> </code> </blockquote> :6. Close External .txt files before ending program <blockquote> <code> <pre> #if USE_LOGGING #if USE_HAND fclose(outHand); #endif #if NUM_QUADS >= 1 fclose(out1); #endif #if NUM_QUADS >= 2 fclose(out2); #endif #if NUM_QUADS >= 3 fclose(out3); #endif #if NUM_QUADS >= 4 fclose(out4); #endif #endif </pre> </code> </blockquote> ==New Client Log Blocks== In the Swarm Client there is a sub-system designed for creating and maintaining Log Blocks. Once you have [[:Firmware#Log Blocks|created a new log block in the Firmware]] that you want to utilize we can do the following: :1. Create an Enable function for the New Log Block (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::enableMagnetometerLogging() { m_tocLogs->registerLoggingBlock("magnetometer", 1000); m_tocLogs->startLogging("mag.x", "magnetometer"); m_tocLogs->startLogging("mag.y", "magnetometer"); m_tocLogs->startLogging("mag.z", "magnetometer"); } </pre> </code> </blockquote> ::This will then register a log block called ''magnetometer'' on the Client, which will be updated every 1000 &mu;s. It will then update the values listed in the block (X, Y, Z of the magnetometer). ::'''Note 1:''' The ''"mag.x"'' term must match the name defined in the Firmware log block (see [[:Firmware#Log Blocks|firmware example 1]]) ::'''Note 2:''' The 2nd input to the ''startLogging'' function needs to match the name of the Client Log block we registered (in this case ''"magnetometer"'') :2. Add the ''enableLogBlock'' function we just made to the list of Log blocks we want at startup (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::startLogging() { // Register the desired sensor readings this->enableStabilizerLogging(); // this->enableGyroscopeLogging(); // this->enableAccelerometerLogging(); this->enableBatteryLogging(); this->enableMagnetometerLogging(); <-----//This is the one we just made // this->enableAltimeterLogging(); // this->enablePIDOutputLogging(); // this->enableRadioRSSILogging(); // this->enableMotorLogging(); return true; } </pre> </code> </blockquote> ::This ''startLogging'' function runs during Crazyflie startup and will start all the log blocks listed. As you can see we have some log blocks commented out currently so that we do NOT start those blocks. :3. Create Functions to Read the variable values during runtime (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> float CCrazyflie::magX() { return this->sensorDoubleValue("mag.x"); } float CCrazyflie::magY() { return this->sensorDoubleValue("mag.y"); } float CCrazyflie::magZ() { return this->sensorDoubleValue("mag.z"); } </pre> </code> </blockquote> ::So now we can use these sensor values, from the Firmware, in the Client code with <code>magX1 = cflieCopter1->magX()</code>. This will store the sensor value in the Client-side variable ''magX1''. :4. (OPTIONAL) We can also create a function to stop logging an individual log block in the Client (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::disableMagnetometerLogging() { m_tocLogs->unregisterLoggingBlock("magnetometer"); } </pre> </code> </blockquote> ::This is straightforward, it just tells the client to stop logging this block. :5. (OPTIONAL) And we can stop ALL log blocks in the client as well (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::stopLogging() { this->disableStabilizerLogging(); this->disableGyroscopeLogging(); this->disableAccelerometerLogging(); this->disableBatteryLogging(); // this->disableMagnetometerLogging(); // this->disableAltimeterLogging(); // this->disablePIDOutputLogging(); this->disableRadioRSSILogging(); this->disableMotorLogging(); return true; } </pre> </code> </blockquote> ::This will disable ALL the logging blocks included in the list. ==MATLAB Parser== '''(**TODO**)''' We use a Matlab script to parse the log files. ===Multi-Logfile Parser=== The primary way we use to visualize the log files is via a very simple and messy MATLAB script. It consists of a bunch of sub-routines that were all thrown together into a single .m file. ====Import Log Data==== <blockquote> <code> <pre> %% Crazyflie Logging Parser [handLog, delimHand] = importdata('hand.txt','\t'); %Imports data from all 5 log files from the Swarm Client [cflie1Log, delim1] = importdata('cflie1.txt','\t'); [cflie2Log, delim2] = importdata('cflie2.txt','\t'); [cflie3Log, delim3] = importdata('cflie3.txt','\t'); [cflie4Log, delim4] = importdata('cflie4.txt','\t'); % handTime = handLog.data(:,1); handRoll = handLog.data(:,3); handPitch = handLog.data(:,5); handYaw = handLog.data(:,7); handX = handLog.data(:,9); %Assigns Hand Data to user-friendly variable names handY = handLog.data(:,11); handZ = handLog.data(:,13); handLoopTime = handLog.data(:,15); handLoopTimeDelta = handLog.data(:,17); % cflie1Time = cflie1Log.data(:,1); cflie1Roll = cflie1Log.data(:,3); cflie1Pitch = cflie1Log.data(:,5); %Assigns Crazyflie1 Data to user-friendly variable names cflie1Yaw = cflie1Log.data(:,7); cflie1X = cflie1Log.data(:,9); cflie1Y = cflie1Log.data(:,11); cflie1Z = cflie1Log.data(:,13); cflie1CamYaw = cflie1Log.data(:,15); cflie1CorrectedYaw = cflie1Log.data(:,17); cflie1LoopTimeTotal = cflie1Log.data(:,19); cflie1LoopTimeTotalDelta = cflie1Log.data(:,21); cflie1LoopTime = cflie1Log.data(:,23); cflie1LoopTimeDelta = cflie1Log.data(:,25); cflie1VrpnPacketDelta = cflie1Log.data(:,27); cflie1VrpnPacketTime = cflie1Log.data(:,29); cflie1VrpnPacketBackup = cflie1Log.data(:,31); % cflie1XSetpoint = cflie1Log.data(:,33); % cflie1YSetpoint = cflie1Log.data(:,35); % cflie1ZSetpoint = cflie1Log.data(:,37); % cflie1YawSetpoint = cflie1Log.data(:,39); % cflie1PitchDesired = cflie1Log.data(:,41); % cflie1RollDesired = cflie1Log.data(:,43); % cflie1YawDesired = cflie1Log.data(:,45); % cflie1ThrustDesired = cflie1Log.data(:,47); % cflie1RadioRSSI = cflie1Log.data(:,49); % cflie1CamYawRad = cflie1Log.data(:,51); % cflie1CamPitchRad = cflie1Log.data(:,53); % cflie1CamRollRad = cflie1Log.data(:,55); % cflie1Motor1 = cflie1Log.data(:,57); % cflie1Motor2 = cflie1Log.data(:,59); % cflie1Motor3 = cflie1Log.data(:,61); % cflie1Motor4 = cflie1Log.data(:,63); % cflie1RollRate = cflie1Log.data(:,65); % cflie1PitchRate = cflie1Log.data(:,67); % cflie1YawRate = cflie1Log.data(:,69); ... ... ... (same for Crazyflie 2, 3, and 4..) ... ... </pre> </code> </blockquote> ::'''Note:''' This list needs to match the log file length that the Swarm Client creates (comment out as needed) ====Plotting X and Y Position of Crazyflies==== :The plots look like this: ::[[Image:XPositionPlot.png|400px]] [[Image:YPositionPlot.png|400px]] <blockquote> <code> <pre> %% Plot X Using ImportData figure(8) %Plotting X-Positions hold off plot(cflie1Time,cflie1X, '-b') hold on % plot(cflie1Time,cflie1XSetpoint, '-.b') % plot(cflie2Time,cflie2X, '-g') % plot(cflie2Time,cflie2XSetpoint, '-.g') % plot(cflie3Time,cflie3X, '-k') % plot(cflie3Time,cflie3XSetpoint, '-.k') % plot(cflie4Time,cflie4X, '-y') % plot(handTime, handX, '-r') % plot(cflie4Time,cflie4XSetpoint, '-.y') title 'Crazyflie X-Positions' legend('Crazyflie 1','Crazyflie 2','Crazyflie3', 'Crazyflie4', 'Hand') xlabel 'Time (seconds)' ylabel 'X-Position (m)' grid on % legend('Crazyflie 1','Setpoint', 'Crazyflie 2','Setpoint', 'Crazyflie3','Setpoint', 'Crazyflie4','Setpoint') % % figure(9) %Plotting Y-Positions hold off plot(cflie1Time,cflie1Y, '-b') hold on % plot(cflie1Time,cflie1YSetpoint, '-.b') % plot(cflie2Time,cflie2Y, '-g') % plot(cflie2Time,cflie2YSetpoint, '-.g') % plot(cflie3Time,cflie3Y, '-k') % plot(cflie3Time,cflie3YSetpoint, '-.k') % plot(cflie4Time,cflie4Y, '-y') % plot(cflie3Time,cflie3YSetpoint, '-.y') % plot(handTime, handY, '-r') title 'Crazyflie Y-Positions' legend('Crazyflie 1','Crazyflie 2','Crazyflie3', 'Crazyflie4', 'Hand') % legend('Crazyflie 1', 'Setpoint','Crazyflie 2', 'Setpoint','Crazyflie3','Setpoint', 'Crazyflie4','Setpoint') xlabel 'Time (seconds)' ylabel 'Y-Position (m)' grid on </pre> </code> </blockquote> ====Plotting Loop Timing==== :This sub-routine plots a 3-piece subplot: :#Z-Positions (Height) of all 4 Crazyflies :#Time it takes for each Crazyflie Callback to finish :#Time between subsequent Callback calls (Loop Deltas) :Resulting in this Plot ::[[Image:HandModeTimingFigure.JPG|700px]] <blockquote> <code> <pre> figure(7) subplot(3,1,1) hold off plot(cflie1Time,cflie1Z,'-b') hold on plot(cflie2Time,cflie2Z,'-g') plot(cflie3Time,cflie3Z,'-k') plot(cflie4Time,cflie4Z,'-y') title 'Crazyflie Z (Height)' legend('Crazyflie 1', 'Crazyflie2', 'Crazyflie3', 'Crazyflie4','Location','NorthWest') ylabel 'Height (m)' grid on subplot(3,1,2) hold off plot(cflie1Time(4:end),cflie1LoopTime(4:end),'-b') hold on plot(cflie2Time(4:end),cflie2LoopTime(4:end),'-g') plot(cflie3Time(4:end),cflie3LoopTime(4:end),'-k') plot(cflie4Time(4:end),cflie4LoopTime(4:end),'-y') title 'Loop Timing' legend('Callback 1', 'Callback 2', 'Callback3', 'Callback4','Location','NorthWest') ylabel 'Loop Time (seconds)' grid on subplot(3,1,3) hold off plot(cflie1Time(4:end),cflie1LoopTimeDelta(4:end),'-b') hold on plot(cflie2Time(4:end),cflie2LoopTimeDelta(4:end),'-g') plot(cflie3Time(4:end),cflie3LoopTimeDelta(4:end),'-k') plot(cflie4Time(4:end),cflie4LoopTimeDelta(4:end),'-y') title 'Time Between Loop Calls' legend('Callback 1', 'Callback 2', 'Callback3', 'Callback4','Location','NorthWest') ylabel 'Loop Deltas (seconds)' xlabel 'Time (seconds)' grid on </pre> </code> </blockquote> ====Hand Mode Position Plot==== :This sub-routine plots a 4-piece subplot: :#X-Positions of all 4 Crazyflies and Hand :#Y-Positions of all 4 Crazyflies and Hand :#Z-Position of Hand (to show position based Gestures) :#Pitch Angle of Hand (to show rotation based Gestures) :Resulting in this Plot (w/o added annotations) ::[[Image:HandModePlot.jpg|700px]] <blockquote> <code> <pre> figure(12) subplot(4,1,1) hold off plot(cflie1Time,cflie1X,'-b') hold on plot(cflie2Time,cflie2X,'-g') plot(cflie3Time,cflie3X,'-k') plot(cflie4Time,cflie4X,'-y') plot(handTime, handX, '-r') title 'X Position' legend('Crazyflie 1', 'Crazyflie2', 'Crazyflie3', 'Crazyflie4','Hand') ylabel 'X Position (m)' grid on subplot(4,1,2) hold off plot(cflie1Time,cflie1Y,'-b') hold on plot(cflie2Time,cflie2Y,'-g') plot(cflie3Time,cflie3Y,'-k') plot(cflie4Time,cflie4Y,'-y') plot(handTime, handY, '-r') title 'Y Position' legend('Crazyflie 1', 'Crazyflie2', 'Crazyflie3', 'Crazyflie4','Hand') ylabel 'Y Position (m)' grid on subplot(4,1,3) hold off plot(handTime, handZ, '-r') title 'Hand Z Position' legend('Hand Height') ylabel 'Height (m)' grid on subplot(4,1,4) hold off plot(handTime, handPitch, '-r') title 'Hand Pitch' legend('Hand Pitch') ylabel 'Angle (rad)' grid on </pre> </code> </blockquote> ===[http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool Universal Lab Parser (Alternative)]=== Alternatively, the lab has a unified logging format that can be read by a universal log parser. More information about this parsing method [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool can be found here] The Swarm Platform log files are compatible with this format and can be used just as any other lab log files. The problem is that this parser can '''only view a single text file at a time'''. This makes comparisons and plotting across all Crazyflies in the swarm very very difficult. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 4433451573fd161012bd01af3b9fe94105396103 241 240 2016-08-02T19:48:05Z Jnoronha 3 /* MATLAB Parser */ removed the TODO wikitext text/x-wiki The logging system is the most important analysis tool we have. This allows us to export any variable data we want out to an external text file. This way we can use any data processor to parse the data. (Excel, MATLAB, R, etc.) ==Client-Side External Log Files== We first need to initialize the log files and prepare them before each test. :1. Create empty File Pointers (code in 'eris_vrpn.cpp') <blockquote> <code> <pre> FILE * outHand = NULL; FILE * out1 = NULL; FILE * out2 = NULL; FILE * out3 = NULL; FILE * out4 = NULL; </pre> </code> </blockquote> :2. Make sure Logging is Enabled (and Basic Logging if desired) <blockquote> <code> <pre> #define USE_VRPN 1 #define USE_KEYBOARD 1 #define USE_PRINTOUT 0 #define USE_LOGGING 1 <---//Enables Full Logging #define USE_BASIC_LOGGING 1 <---//Only logs the necessities (FULL LOGGING MUST BE ENABLED FOR THIS TO WORK) #define USE_PR_YAW_CORRECT 0 #define USE_HAND 1 </pre> </code> </blockquote> :3. Create Log File Header (# = Log File Title, % = List of Variable Names, & = List of Variable Units) ::'''Note 1:''' This example is using BASIC_LOGGING 1, ::'''Note 2:''' Variables and units are separated by a double tab '\t\t' (Does not have to be '\t\t' any delimiter works) <blockquote> <code> <pre> const char * logHeaderHand = "#Hand Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tLoopTime\t\tLoopTimeDelta\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tseconds\t\tseconds\n"; const char * logHeader1 = "#Crazyflie1 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\t\tRadioRSSI\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\t\tstrength\n"; const char * logHeader2 = "#Crazyflie2 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader3 = "#Crazyflie3 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader4 = "#Crazyflie4 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; </pre> </code> </blockquote> :4. Open External .txt file and Print Header into file <blockquote> <code> <pre> #if USE_HAND outHand = fopen("hand.txt", "w"); //Opens text file with write permission if(outHand == NULL) { printf("Could not open hand.log: errno %d\n", errno); exit(-1); } fprintf(outHand, "%s\n", logHeaderHand); //Prints log header into corresponding file #endif if(cflieCopter1) //Checks to see if cflieCopter pointer has been initialized before opening file { out1 = fopen("cflie1.txt", "w"); if(out1 == NULL) { printf("Could not open cflie1.log: errno %d\n", errno); exit(-1); } fprintf(out1, "%s\n", logHeader1); } if(cflieCopter2) { out2 = fopen("cflie2.txt", "w"); if(out2 == NULL) { printf("Could not open cflie2.log:errno %d\n", errno); exit(-1); } fprintf(out2, "%s\n", logHeader2); } if(cflieCopter3) { out3 = fopen("cflie3.txt", "w"); if(out3 == NULL) { printf("Could not open cflie3.log:errno %d\n", errno); exit(-1); } fprintf(out3, "%s\n", logHeader3); } if(cflieCopter4) { out4 = fopen("cflie4.txt", "w"); if(out4 == NULL) { printf("Could not open cflie4.log:errno %d\n", errno); exit(-1); } fprintf(out4, "%s\n", logHeader4); } </pre> </code> </blockquote> :5. Init has Completed (Start Program Loop) Prints Variable values to file... ::'''Note 1:''' This code is run at the end of the Callback for each Crazyflie initialized (Executes once per new data packet) ::'''Note 2:''' This example is using BASIC_LOGGING, and is only showing Crazyflie1's code. <blockquote> <code> <pre> fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); fprintf(out1, "\n"); </pre> </code> </blockquote> :6. Close External .txt files before ending program <blockquote> <code> <pre> #if USE_LOGGING #if USE_HAND fclose(outHand); #endif #if NUM_QUADS >= 1 fclose(out1); #endif #if NUM_QUADS >= 2 fclose(out2); #endif #if NUM_QUADS >= 3 fclose(out3); #endif #if NUM_QUADS >= 4 fclose(out4); #endif #endif </pre> </code> </blockquote> ==New Client Log Blocks== In the Swarm Client there is a sub-system designed for creating and maintaining Log Blocks. Once you have [[:Firmware#Log Blocks|created a new log block in the Firmware]] that you want to utilize we can do the following: :1. Create an Enable function for the New Log Block (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::enableMagnetometerLogging() { m_tocLogs->registerLoggingBlock("magnetometer", 1000); m_tocLogs->startLogging("mag.x", "magnetometer"); m_tocLogs->startLogging("mag.y", "magnetometer"); m_tocLogs->startLogging("mag.z", "magnetometer"); } </pre> </code> </blockquote> ::This will then register a log block called ''magnetometer'' on the Client, which will be updated every 1000 &mu;s. It will then update the values listed in the block (X, Y, Z of the magnetometer). ::'''Note 1:''' The ''"mag.x"'' term must match the name defined in the Firmware log block (see [[:Firmware#Log Blocks|firmware example 1]]) ::'''Note 2:''' The 2nd input to the ''startLogging'' function needs to match the name of the Client Log block we registered (in this case ''"magnetometer"'') :2. Add the ''enableLogBlock'' function we just made to the list of Log blocks we want at startup (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::startLogging() { // Register the desired sensor readings this->enableStabilizerLogging(); // this->enableGyroscopeLogging(); // this->enableAccelerometerLogging(); this->enableBatteryLogging(); this->enableMagnetometerLogging(); <-----//This is the one we just made // this->enableAltimeterLogging(); // this->enablePIDOutputLogging(); // this->enableRadioRSSILogging(); // this->enableMotorLogging(); return true; } </pre> </code> </blockquote> ::This ''startLogging'' function runs during Crazyflie startup and will start all the log blocks listed. As you can see we have some log blocks commented out currently so that we do NOT start those blocks. :3. Create Functions to Read the variable values during runtime (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> float CCrazyflie::magX() { return this->sensorDoubleValue("mag.x"); } float CCrazyflie::magY() { return this->sensorDoubleValue("mag.y"); } float CCrazyflie::magZ() { return this->sensorDoubleValue("mag.z"); } </pre> </code> </blockquote> ::So now we can use these sensor values, from the Firmware, in the Client code with <code>magX1 = cflieCopter1->magX()</code>. This will store the sensor value in the Client-side variable ''magX1''. :4. (OPTIONAL) We can also create a function to stop logging an individual log block in the Client (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::disableMagnetometerLogging() { m_tocLogs->unregisterLoggingBlock("magnetometer"); } </pre> </code> </blockquote> ::This is straightforward, it just tells the client to stop logging this block. :5. (OPTIONAL) And we can stop ALL log blocks in the client as well (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::stopLogging() { this->disableStabilizerLogging(); this->disableGyroscopeLogging(); this->disableAccelerometerLogging(); this->disableBatteryLogging(); // this->disableMagnetometerLogging(); // this->disableAltimeterLogging(); // this->disablePIDOutputLogging(); this->disableRadioRSSILogging(); this->disableMotorLogging(); return true; } </pre> </code> </blockquote> ::This will disable ALL the logging blocks included in the list. ==MATLAB Parser== We use a Matlab script to parse the log files. ===Multi-Logfile Parser=== The primary way we use to visualize the log files is via a very simple and messy MATLAB script. It consists of a bunch of sub-routines that were all thrown together into a single .m file. ====Import Log Data==== <blockquote> <code> <pre> %% Crazyflie Logging Parser [handLog, delimHand] = importdata('hand.txt','\t'); %Imports data from all 5 log files from the Swarm Client [cflie1Log, delim1] = importdata('cflie1.txt','\t'); [cflie2Log, delim2] = importdata('cflie2.txt','\t'); [cflie3Log, delim3] = importdata('cflie3.txt','\t'); [cflie4Log, delim4] = importdata('cflie4.txt','\t'); % handTime = handLog.data(:,1); handRoll = handLog.data(:,3); handPitch = handLog.data(:,5); handYaw = handLog.data(:,7); handX = handLog.data(:,9); %Assigns Hand Data to user-friendly variable names handY = handLog.data(:,11); handZ = handLog.data(:,13); handLoopTime = handLog.data(:,15); handLoopTimeDelta = handLog.data(:,17); % cflie1Time = cflie1Log.data(:,1); cflie1Roll = cflie1Log.data(:,3); cflie1Pitch = cflie1Log.data(:,5); %Assigns Crazyflie1 Data to user-friendly variable names cflie1Yaw = cflie1Log.data(:,7); cflie1X = cflie1Log.data(:,9); cflie1Y = cflie1Log.data(:,11); cflie1Z = cflie1Log.data(:,13); cflie1CamYaw = cflie1Log.data(:,15); cflie1CorrectedYaw = cflie1Log.data(:,17); cflie1LoopTimeTotal = cflie1Log.data(:,19); cflie1LoopTimeTotalDelta = cflie1Log.data(:,21); cflie1LoopTime = cflie1Log.data(:,23); cflie1LoopTimeDelta = cflie1Log.data(:,25); cflie1VrpnPacketDelta = cflie1Log.data(:,27); cflie1VrpnPacketTime = cflie1Log.data(:,29); cflie1VrpnPacketBackup = cflie1Log.data(:,31); % cflie1XSetpoint = cflie1Log.data(:,33); % cflie1YSetpoint = cflie1Log.data(:,35); % cflie1ZSetpoint = cflie1Log.data(:,37); % cflie1YawSetpoint = cflie1Log.data(:,39); % cflie1PitchDesired = cflie1Log.data(:,41); % cflie1RollDesired = cflie1Log.data(:,43); % cflie1YawDesired = cflie1Log.data(:,45); % cflie1ThrustDesired = cflie1Log.data(:,47); % cflie1RadioRSSI = cflie1Log.data(:,49); % cflie1CamYawRad = cflie1Log.data(:,51); % cflie1CamPitchRad = cflie1Log.data(:,53); % cflie1CamRollRad = cflie1Log.data(:,55); % cflie1Motor1 = cflie1Log.data(:,57); % cflie1Motor2 = cflie1Log.data(:,59); % cflie1Motor3 = cflie1Log.data(:,61); % cflie1Motor4 = cflie1Log.data(:,63); % cflie1RollRate = cflie1Log.data(:,65); % cflie1PitchRate = cflie1Log.data(:,67); % cflie1YawRate = cflie1Log.data(:,69); ... ... ... (same for Crazyflie 2, 3, and 4..) ... ... </pre> </code> </blockquote> ::'''Note:''' This list needs to match the log file length that the Swarm Client creates (comment out as needed) ====Plotting X and Y Position of Crazyflies==== :The plots look like this: ::[[Image:XPositionPlot.png|400px]] [[Image:YPositionPlot.png|400px]] <blockquote> <code> <pre> %% Plot X Using ImportData figure(8) %Plotting X-Positions hold off plot(cflie1Time,cflie1X, '-b') hold on % plot(cflie1Time,cflie1XSetpoint, '-.b') % plot(cflie2Time,cflie2X, '-g') % plot(cflie2Time,cflie2XSetpoint, '-.g') % plot(cflie3Time,cflie3X, '-k') % plot(cflie3Time,cflie3XSetpoint, '-.k') % plot(cflie4Time,cflie4X, '-y') % plot(handTime, handX, '-r') % plot(cflie4Time,cflie4XSetpoint, '-.y') title 'Crazyflie X-Positions' legend('Crazyflie 1','Crazyflie 2','Crazyflie3', 'Crazyflie4', 'Hand') xlabel 'Time (seconds)' ylabel 'X-Position (m)' grid on % legend('Crazyflie 1','Setpoint', 'Crazyflie 2','Setpoint', 'Crazyflie3','Setpoint', 'Crazyflie4','Setpoint') % % figure(9) %Plotting Y-Positions hold off plot(cflie1Time,cflie1Y, '-b') hold on % plot(cflie1Time,cflie1YSetpoint, '-.b') % plot(cflie2Time,cflie2Y, '-g') % plot(cflie2Time,cflie2YSetpoint, '-.g') % plot(cflie3Time,cflie3Y, '-k') % plot(cflie3Time,cflie3YSetpoint, '-.k') % plot(cflie4Time,cflie4Y, '-y') % plot(cflie3Time,cflie3YSetpoint, '-.y') % plot(handTime, handY, '-r') title 'Crazyflie Y-Positions' legend('Crazyflie 1','Crazyflie 2','Crazyflie3', 'Crazyflie4', 'Hand') % legend('Crazyflie 1', 'Setpoint','Crazyflie 2', 'Setpoint','Crazyflie3','Setpoint', 'Crazyflie4','Setpoint') xlabel 'Time (seconds)' ylabel 'Y-Position (m)' grid on </pre> </code> </blockquote> ====Plotting Loop Timing==== :This sub-routine plots a 3-piece subplot: :#Z-Positions (Height) of all 4 Crazyflies :#Time it takes for each Crazyflie Callback to finish :#Time between subsequent Callback calls (Loop Deltas) :Resulting in this Plot ::[[Image:HandModeTimingFigure.JPG|700px]] <blockquote> <code> <pre> figure(7) subplot(3,1,1) hold off plot(cflie1Time,cflie1Z,'-b') hold on plot(cflie2Time,cflie2Z,'-g') plot(cflie3Time,cflie3Z,'-k') plot(cflie4Time,cflie4Z,'-y') title 'Crazyflie Z (Height)' legend('Crazyflie 1', 'Crazyflie2', 'Crazyflie3', 'Crazyflie4','Location','NorthWest') ylabel 'Height (m)' grid on subplot(3,1,2) hold off plot(cflie1Time(4:end),cflie1LoopTime(4:end),'-b') hold on plot(cflie2Time(4:end),cflie2LoopTime(4:end),'-g') plot(cflie3Time(4:end),cflie3LoopTime(4:end),'-k') plot(cflie4Time(4:end),cflie4LoopTime(4:end),'-y') title 'Loop Timing' legend('Callback 1', 'Callback 2', 'Callback3', 'Callback4','Location','NorthWest') ylabel 'Loop Time (seconds)' grid on subplot(3,1,3) hold off plot(cflie1Time(4:end),cflie1LoopTimeDelta(4:end),'-b') hold on plot(cflie2Time(4:end),cflie2LoopTimeDelta(4:end),'-g') plot(cflie3Time(4:end),cflie3LoopTimeDelta(4:end),'-k') plot(cflie4Time(4:end),cflie4LoopTimeDelta(4:end),'-y') title 'Time Between Loop Calls' legend('Callback 1', 'Callback 2', 'Callback3', 'Callback4','Location','NorthWest') ylabel 'Loop Deltas (seconds)' xlabel 'Time (seconds)' grid on </pre> </code> </blockquote> ====Hand Mode Position Plot==== :This sub-routine plots a 4-piece subplot: :#X-Positions of all 4 Crazyflies and Hand :#Y-Positions of all 4 Crazyflies and Hand :#Z-Position of Hand (to show position based Gestures) :#Pitch Angle of Hand (to show rotation based Gestures) :Resulting in this Plot (w/o added annotations) ::[[Image:HandModePlot.jpg|700px]] <blockquote> <code> <pre> figure(12) subplot(4,1,1) hold off plot(cflie1Time,cflie1X,'-b') hold on plot(cflie2Time,cflie2X,'-g') plot(cflie3Time,cflie3X,'-k') plot(cflie4Time,cflie4X,'-y') plot(handTime, handX, '-r') title 'X Position' legend('Crazyflie 1', 'Crazyflie2', 'Crazyflie3', 'Crazyflie4','Hand') ylabel 'X Position (m)' grid on subplot(4,1,2) hold off plot(cflie1Time,cflie1Y,'-b') hold on plot(cflie2Time,cflie2Y,'-g') plot(cflie3Time,cflie3Y,'-k') plot(cflie4Time,cflie4Y,'-y') plot(handTime, handY, '-r') title 'Y Position' legend('Crazyflie 1', 'Crazyflie2', 'Crazyflie3', 'Crazyflie4','Hand') ylabel 'Y Position (m)' grid on subplot(4,1,3) hold off plot(handTime, handZ, '-r') title 'Hand Z Position' legend('Hand Height') ylabel 'Height (m)' grid on subplot(4,1,4) hold off plot(handTime, handPitch, '-r') title 'Hand Pitch' legend('Hand Pitch') ylabel 'Angle (rad)' grid on </pre> </code> </blockquote> ===[http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool Universal Lab Parser (Alternative)]=== Alternatively, the lab has a unified logging format that can be read by a universal log parser. More information about this parsing method [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool can be found here] The Swarm Platform log files are compatible with this format and can be used just as any other lab log files. The problem is that this parser can '''only view a single text file at a time'''. This makes comparisons and plotting across all Crazyflies in the swarm very very difficult. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 188340f58fc72b378c1e896f689282234ae9abde 242 241 2016-08-02T19:53:12Z Jnoronha 3 /* MATLAB Parser */ added description to top and note about commented out matlab sub-routines wikitext text/x-wiki The logging system is the most important analysis tool we have. This allows us to export any variable data we want out to an external text file. This way we can use any data processor to parse the data. (Excel, MATLAB, R, etc.) ==Client-Side External Log Files== We first need to initialize the log files and prepare them before each test. :1. Create empty File Pointers (code in 'eris_vrpn.cpp') <blockquote> <code> <pre> FILE * outHand = NULL; FILE * out1 = NULL; FILE * out2 = NULL; FILE * out3 = NULL; FILE * out4 = NULL; </pre> </code> </blockquote> :2. Make sure Logging is Enabled (and Basic Logging if desired) <blockquote> <code> <pre> #define USE_VRPN 1 #define USE_KEYBOARD 1 #define USE_PRINTOUT 0 #define USE_LOGGING 1 <---//Enables Full Logging #define USE_BASIC_LOGGING 1 <---//Only logs the necessities (FULL LOGGING MUST BE ENABLED FOR THIS TO WORK) #define USE_PR_YAW_CORRECT 0 #define USE_HAND 1 </pre> </code> </blockquote> :3. Create Log File Header (# = Log File Title, % = List of Variable Names, & = List of Variable Units) ::'''Note 1:''' This example is using BASIC_LOGGING 1, ::'''Note 2:''' Variables and units are separated by a double tab '\t\t' (Does not have to be '\t\t' any delimiter works) <blockquote> <code> <pre> const char * logHeaderHand = "#Hand Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tLoopTime\t\tLoopTimeDelta\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tseconds\t\tseconds\n"; const char * logHeader1 = "#Crazyflie1 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\t\tRadioRSSI\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\t\tstrength\n"; const char * logHeader2 = "#Crazyflie2 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader3 = "#Crazyflie3 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; const char * logHeader4 = "#Crazyflie4 Log File\n\ %Time\t\tPitch\t\tRoll\t\tYaw\t\tX\t\tY\t\tZ\t\tCamYaw\t\tCorrectedYaw\t\tLoopTimeTotal\t\tLoopTimeTotalDelta\t\tLoopTime\t\tLoopTimeDelta\t\tvrpnPacketDelta\t\tvrpnPacketTime\t\tvrpnPacketBackup\n\ &sec\t\tdegrees\t\tdegrees\t\tdegrees\t\tmeters\t\tmeters\t\tmeters\t\tdegrees\t\tdegrees\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tseconds\t\tpackets\n"; </pre> </code> </blockquote> :4. Open External .txt file and Print Header into file <blockquote> <code> <pre> #if USE_HAND outHand = fopen("hand.txt", "w"); //Opens text file with write permission if(outHand == NULL) { printf("Could not open hand.log: errno %d\n", errno); exit(-1); } fprintf(outHand, "%s\n", logHeaderHand); //Prints log header into corresponding file #endif if(cflieCopter1) //Checks to see if cflieCopter pointer has been initialized before opening file { out1 = fopen("cflie1.txt", "w"); if(out1 == NULL) { printf("Could not open cflie1.log: errno %d\n", errno); exit(-1); } fprintf(out1, "%s\n", logHeader1); } if(cflieCopter2) { out2 = fopen("cflie2.txt", "w"); if(out2 == NULL) { printf("Could not open cflie2.log:errno %d\n", errno); exit(-1); } fprintf(out2, "%s\n", logHeader2); } if(cflieCopter3) { out3 = fopen("cflie3.txt", "w"); if(out3 == NULL) { printf("Could not open cflie3.log:errno %d\n", errno); exit(-1); } fprintf(out3, "%s\n", logHeader3); } if(cflieCopter4) { out4 = fopen("cflie4.txt", "w"); if(out4 == NULL) { printf("Could not open cflie4.log:errno %d\n", errno); exit(-1); } fprintf(out4, "%s\n", logHeader4); } </pre> </code> </blockquote> :5. Init has Completed (Start Program Loop) Prints Variable values to file... ::'''Note 1:''' This code is run at the end of the Callback for each Crazyflie initialized (Executes once per new data packet) ::'''Note 2:''' This example is using BASIC_LOGGING, and is only showing Crazyflie1's code. <blockquote> <code> <pre> fprintf(out1, "%.6f\t\t", cflieCopter1->currentTime() - initTime1 ); fprintf(out1, "%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%.6f\t\t%d\t\t%d", cflieCopter1->roll(), cflieCopter1->pitch(), quadYaw1, t.pos[0], t.pos[1], -t.pos[2], camYawDeg1, correctedYaw1, loopTimeTotal, loopTimeTotalDelta, loopTime1, loopTime1Delta, vrpnPacketDelta1, vrpnPacketTime1, vrpnPacketBackup1, cflieCopter1->radioRSSI()); fprintf(out1, "\n"); </pre> </code> </blockquote> :6. Close External .txt files before ending program <blockquote> <code> <pre> #if USE_LOGGING #if USE_HAND fclose(outHand); #endif #if NUM_QUADS >= 1 fclose(out1); #endif #if NUM_QUADS >= 2 fclose(out2); #endif #if NUM_QUADS >= 3 fclose(out3); #endif #if NUM_QUADS >= 4 fclose(out4); #endif #endif </pre> </code> </blockquote> ==New Client Log Blocks== In the Swarm Client there is a sub-system designed for creating and maintaining Log Blocks. Once you have [[:Firmware#Log Blocks|created a new log block in the Firmware]] that you want to utilize we can do the following: :1. Create an Enable function for the New Log Block (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::enableMagnetometerLogging() { m_tocLogs->registerLoggingBlock("magnetometer", 1000); m_tocLogs->startLogging("mag.x", "magnetometer"); m_tocLogs->startLogging("mag.y", "magnetometer"); m_tocLogs->startLogging("mag.z", "magnetometer"); } </pre> </code> </blockquote> ::This will then register a log block called ''magnetometer'' on the Client, which will be updated every 1000 &mu;s. It will then update the values listed in the block (X, Y, Z of the magnetometer). ::'''Note 1:''' The ''"mag.x"'' term must match the name defined in the Firmware log block (see [[:Firmware#Log Blocks|firmware example 1]]) ::'''Note 2:''' The 2nd input to the ''startLogging'' function needs to match the name of the Client Log block we registered (in this case ''"magnetometer"'') :2. Add the ''enableLogBlock'' function we just made to the list of Log blocks we want at startup (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::startLogging() { // Register the desired sensor readings this->enableStabilizerLogging(); // this->enableGyroscopeLogging(); // this->enableAccelerometerLogging(); this->enableBatteryLogging(); this->enableMagnetometerLogging(); <-----//This is the one we just made // this->enableAltimeterLogging(); // this->enablePIDOutputLogging(); // this->enableRadioRSSILogging(); // this->enableMotorLogging(); return true; } </pre> </code> </blockquote> ::This ''startLogging'' function runs during Crazyflie startup and will start all the log blocks listed. As you can see we have some log blocks commented out currently so that we do NOT start those blocks. :3. Create Functions to Read the variable values during runtime (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> float CCrazyflie::magX() { return this->sensorDoubleValue("mag.x"); } float CCrazyflie::magY() { return this->sensorDoubleValue("mag.y"); } float CCrazyflie::magZ() { return this->sensorDoubleValue("mag.z"); } </pre> </code> </blockquote> ::So now we can use these sensor values, from the Firmware, in the Client code with <code>magX1 = cflieCopter1->magX()</code>. This will store the sensor value in the Client-side variable ''magX1''. :4. (OPTIONAL) We can also create a function to stop logging an individual log block in the Client (code in ''CCrazyflie.cpp'') <blockquote> <code> <pre> void CCrazyflie::disableMagnetometerLogging() { m_tocLogs->unregisterLoggingBlock("magnetometer"); } </pre> </code> </blockquote> ::This is straightforward, it just tells the client to stop logging this block. :5. (OPTIONAL) And we can stop ALL log blocks in the client as well (code in ''CCrazyflie.cpp''): <blockquote> <code> <pre> bool CCrazyflie::stopLogging() { this->disableStabilizerLogging(); this->disableGyroscopeLogging(); this->disableAccelerometerLogging(); this->disableBatteryLogging(); // this->disableMagnetometerLogging(); // this->disableAltimeterLogging(); // this->disablePIDOutputLogging(); this->disableRadioRSSILogging(); this->disableMotorLogging(); return true; } </pre> </code> </blockquote> ::This will disable ALL the logging blocks included in the list. ==MATLAB Parser== We use a Matlab script to parse the log files. You can use any program you want to parse the data if you are more comfortable with it, below you will find some details on how we parse the log-files. ===Multi-Logfile Parser=== The primary way we use to visualize the log files is via a very simple and messy MATLAB script. It consists of a bunch of sub-routines that were all thrown together into a single .m file. ====Import Log Data==== <blockquote> <code> <pre> %% Crazyflie Logging Parser [handLog, delimHand] = importdata('hand.txt','\t'); %Imports data from all 5 log files from the Swarm Client [cflie1Log, delim1] = importdata('cflie1.txt','\t'); [cflie2Log, delim2] = importdata('cflie2.txt','\t'); [cflie3Log, delim3] = importdata('cflie3.txt','\t'); [cflie4Log, delim4] = importdata('cflie4.txt','\t'); % handTime = handLog.data(:,1); handRoll = handLog.data(:,3); handPitch = handLog.data(:,5); handYaw = handLog.data(:,7); handX = handLog.data(:,9); %Assigns Hand Data to user-friendly variable names handY = handLog.data(:,11); handZ = handLog.data(:,13); handLoopTime = handLog.data(:,15); handLoopTimeDelta = handLog.data(:,17); % cflie1Time = cflie1Log.data(:,1); cflie1Roll = cflie1Log.data(:,3); cflie1Pitch = cflie1Log.data(:,5); %Assigns Crazyflie1 Data to user-friendly variable names cflie1Yaw = cflie1Log.data(:,7); cflie1X = cflie1Log.data(:,9); cflie1Y = cflie1Log.data(:,11); cflie1Z = cflie1Log.data(:,13); cflie1CamYaw = cflie1Log.data(:,15); cflie1CorrectedYaw = cflie1Log.data(:,17); cflie1LoopTimeTotal = cflie1Log.data(:,19); cflie1LoopTimeTotalDelta = cflie1Log.data(:,21); cflie1LoopTime = cflie1Log.data(:,23); cflie1LoopTimeDelta = cflie1Log.data(:,25); cflie1VrpnPacketDelta = cflie1Log.data(:,27); cflie1VrpnPacketTime = cflie1Log.data(:,29); cflie1VrpnPacketBackup = cflie1Log.data(:,31); % cflie1XSetpoint = cflie1Log.data(:,33); % cflie1YSetpoint = cflie1Log.data(:,35); % cflie1ZSetpoint = cflie1Log.data(:,37); % cflie1YawSetpoint = cflie1Log.data(:,39); % cflie1PitchDesired = cflie1Log.data(:,41); % cflie1RollDesired = cflie1Log.data(:,43); % cflie1YawDesired = cflie1Log.data(:,45); % cflie1ThrustDesired = cflie1Log.data(:,47); % cflie1RadioRSSI = cflie1Log.data(:,49); % cflie1CamYawRad = cflie1Log.data(:,51); % cflie1CamPitchRad = cflie1Log.data(:,53); % cflie1CamRollRad = cflie1Log.data(:,55); % cflie1Motor1 = cflie1Log.data(:,57); % cflie1Motor2 = cflie1Log.data(:,59); % cflie1Motor3 = cflie1Log.data(:,61); % cflie1Motor4 = cflie1Log.data(:,63); % cflie1RollRate = cflie1Log.data(:,65); % cflie1PitchRate = cflie1Log.data(:,67); % cflie1YawRate = cflie1Log.data(:,69); ... ... ... (same for Crazyflie 2, 3, and 4..) ... ... </pre> </code> </blockquote> ::'''Note:''' This list needs to match the log file length that the Swarm Client creates (comment out as needed) ====Plotting X and Y Position of Crazyflies==== :The plots look like this: ::[[Image:XPositionPlot.png|400px]] [[Image:YPositionPlot.png|400px]] <blockquote> <code> <pre> %% Plot X Using ImportData figure(8) %Plotting X-Positions hold off plot(cflie1Time,cflie1X, '-b') hold on % plot(cflie1Time,cflie1XSetpoint, '-.b') % plot(cflie2Time,cflie2X, '-g') % plot(cflie2Time,cflie2XSetpoint, '-.g') % plot(cflie3Time,cflie3X, '-k') % plot(cflie3Time,cflie3XSetpoint, '-.k') % plot(cflie4Time,cflie4X, '-y') % plot(handTime, handX, '-r') % plot(cflie4Time,cflie4XSetpoint, '-.y') title 'Crazyflie X-Positions' legend('Crazyflie 1','Crazyflie 2','Crazyflie3', 'Crazyflie4', 'Hand') xlabel 'Time (seconds)' ylabel 'X-Position (m)' grid on % legend('Crazyflie 1','Setpoint', 'Crazyflie 2','Setpoint', 'Crazyflie3','Setpoint', 'Crazyflie4','Setpoint') % % figure(9) %Plotting Y-Positions hold off plot(cflie1Time,cflie1Y, '-b') hold on % plot(cflie1Time,cflie1YSetpoint, '-.b') % plot(cflie2Time,cflie2Y, '-g') % plot(cflie2Time,cflie2YSetpoint, '-.g') % plot(cflie3Time,cflie3Y, '-k') % plot(cflie3Time,cflie3YSetpoint, '-.k') % plot(cflie4Time,cflie4Y, '-y') % plot(cflie3Time,cflie3YSetpoint, '-.y') % plot(handTime, handY, '-r') title 'Crazyflie Y-Positions' legend('Crazyflie 1','Crazyflie 2','Crazyflie3', 'Crazyflie4', 'Hand') % legend('Crazyflie 1', 'Setpoint','Crazyflie 2', 'Setpoint','Crazyflie3','Setpoint', 'Crazyflie4','Setpoint') xlabel 'Time (seconds)' ylabel 'Y-Position (m)' grid on </pre> </code> </blockquote> ====Plotting Loop Timing==== :This sub-routine plots a 3-piece subplot: :#Z-Positions (Height) of all 4 Crazyflies :#Time it takes for each Crazyflie Callback to finish :#Time between subsequent Callback calls (Loop Deltas) :Resulting in this Plot ::[[Image:HandModeTimingFigure.JPG|700px]] <blockquote> <code> <pre> figure(7) subplot(3,1,1) hold off plot(cflie1Time,cflie1Z,'-b') hold on plot(cflie2Time,cflie2Z,'-g') plot(cflie3Time,cflie3Z,'-k') plot(cflie4Time,cflie4Z,'-y') title 'Crazyflie Z (Height)' legend('Crazyflie 1', 'Crazyflie2', 'Crazyflie3', 'Crazyflie4','Location','NorthWest') ylabel 'Height (m)' grid on subplot(3,1,2) hold off plot(cflie1Time(4:end),cflie1LoopTime(4:end),'-b') hold on plot(cflie2Time(4:end),cflie2LoopTime(4:end),'-g') plot(cflie3Time(4:end),cflie3LoopTime(4:end),'-k') plot(cflie4Time(4:end),cflie4LoopTime(4:end),'-y') title 'Loop Timing' legend('Callback 1', 'Callback 2', 'Callback3', 'Callback4','Location','NorthWest') ylabel 'Loop Time (seconds)' grid on subplot(3,1,3) hold off plot(cflie1Time(4:end),cflie1LoopTimeDelta(4:end),'-b') hold on plot(cflie2Time(4:end),cflie2LoopTimeDelta(4:end),'-g') plot(cflie3Time(4:end),cflie3LoopTimeDelta(4:end),'-k') plot(cflie4Time(4:end),cflie4LoopTimeDelta(4:end),'-y') title 'Time Between Loop Calls' legend('Callback 1', 'Callback 2', 'Callback3', 'Callback4','Location','NorthWest') ylabel 'Loop Deltas (seconds)' xlabel 'Time (seconds)' grid on </pre> </code> </blockquote> ====Hand Mode Position Plot==== :This sub-routine plots a 4-piece subplot: :#X-Positions of all 4 Crazyflies and Hand :#Y-Positions of all 4 Crazyflies and Hand :#Z-Position of Hand (to show position based Gestures) :#Pitch Angle of Hand (to show rotation based Gestures) :Resulting in this Plot (w/o added annotations) ::[[Image:HandModePlot.jpg|700px]] <blockquote> <code> <pre> figure(12) subplot(4,1,1) hold off plot(cflie1Time,cflie1X,'-b') hold on plot(cflie2Time,cflie2X,'-g') plot(cflie3Time,cflie3X,'-k') plot(cflie4Time,cflie4X,'-y') plot(handTime, handX, '-r') title 'X Position' legend('Crazyflie 1', 'Crazyflie2', 'Crazyflie3', 'Crazyflie4','Hand') ylabel 'X Position (m)' grid on subplot(4,1,2) hold off plot(cflie1Time,cflie1Y,'-b') hold on plot(cflie2Time,cflie2Y,'-g') plot(cflie3Time,cflie3Y,'-k') plot(cflie4Time,cflie4Y,'-y') plot(handTime, handY, '-r') title 'Y Position' legend('Crazyflie 1', 'Crazyflie2', 'Crazyflie3', 'Crazyflie4','Hand') ylabel 'Y Position (m)' grid on subplot(4,1,3) hold off plot(handTime, handZ, '-r') title 'Hand Z Position' legend('Hand Height') ylabel 'Height (m)' grid on subplot(4,1,4) hold off plot(handTime, handPitch, '-r') title 'Hand Pitch' legend('Hand Pitch') ylabel 'Angle (rad)' grid on </pre> </code> </blockquote> '''NOTE:''' There are many other sub-routines in the MATLAB script that we are not currently using, this is just a sample of some of the more useful data visualization methods we have in place already. You can see more in ''cflieLogParser.m'' (located in the Swarm Client directory). ===[http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool Universal Lab Parser (Alternative)]=== Alternatively, the lab has a unified logging format that can be read by a universal log parser. More information about this parsing method [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool can be found here] The Swarm Platform log files are compatible with this format and can be used just as any other lab log files. The problem is that this parser can '''only view a single text file at a time'''. This makes comparisons and plotting across all Crazyflies in the swarm very very difficult. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 9312cbcce1cf7c213864db579c28476b7feb0ab7 File:XPositionPlot.png 6 67 235 2016-08-02T19:24:31Z Jnoronha 3 X position plot produced by the matlab logfile parser wikitext text/x-wiki X position plot produced by the matlab logfile parser e330d18c0d830813b11e4a5551b13d1e20d2a2e5 File:YPositionPlot.png 6 68 236 2016-08-02T19:24:48Z Jnoronha 3 Y position plot produced by the matlab logfile parser wikitext text/x-wiki Y position plot produced by the matlab logfile parser 0cbfa9ce48512c39aeee38c0b9d34ec8a20e813d File:HandModePlot.jpg 6 69 237 2016-08-02T19:25:18Z Jnoronha 3 Hand Mode demo plot produced by the matlab logfile parser wikitext text/x-wiki Hand Mode demo plot produced by the matlab logfile parser b68031a6bf9dcc7b0a69a5763515d6025eda6087 File:HandModeTimingFigure.JPG 6 70 238 2016-08-02T19:25:43Z Jnoronha 3 Hand Mode timing plot produced by the matlab logfile parser wikitext text/x-wiki Hand Mode timing plot produced by the matlab logfile parser ebaca8b8857776b9ef950bf6d7cdf786cbbf37f1 FAQ 0 40 244 136 2016-08-02T19:55:22Z Jnoronha 3 added matlab parser wikitext text/x-wiki Here you can find some Frequently Asked Questions: :'''1. How do I change the Radio Channel?''' ::Find out here: [[:USB Radio#Changing Radio Channel|Changing the Radio Channel]] :'''2. How do I use Log Blocks?''' ::*Creating and using [[:Logging#Client-Side External Log Files|External Client-side Log Files]] ::*Creating [[:Firmware#New Firmware Log Blocks|New Log Blocks in Firmware]] ::*Creating and Using [[:Logging#New Client Log Blocks|New Log Blocks in Client]] :'''3. I just want to run the code, how do I run it?''' ::See [[:PC Client Software#Using the Swarm Client|Using the Swarm Client]] :'''4. What are the Keyboard Commands for flying the Crazyflie?''' ::You can find a full list of all the Key Commands in [[:Keyboard Commands]] ::(Alternatively: See '''Step 4''' of [[:PC Client Software#Using the Swarm Client|Using the Swarm Client]]) :'''5. How do I plot the Log Files that the Crazyflie Swarm Creates?''' ::See the [[:Logging#MATLAB Parser|MATLAB Parser]] section for examples. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 1b2d0d04b3d42a0b8e78bcd9d5b2e1797dc4488c Crazyflie Swarm 0 2 245 177 2016-08-02T19:59:51Z Jnoronha 3 added swarm architecture wikitext text/x-wiki The Crazyflie Swarm is a Networked Control platform designed for students to learn more about control and for researchers that wish to apply their research in practice. Platform development was started during the Summer of 2015 and continues to this day. Here you will find descriptions on how the platform works, how you can use it, and how you can get involved in developing the platform further! == Frequently Asked Questions == For help with common problems and troubleshooting please see the [[FAQ]]. == Background == The Crazyflie Swarm platform is based off of the ''Crazyflie'' Nano-quadcopter produced and maintained by [https://www.bitcraze.io/ Bitcraze]. The ''Crazyflie'' is completely open-source so we are able to look at and modify any part of the code and customize it to our needs. === Major Platform Components: === [[Image: High_Level_Figure_(Single_Radio_Single_Crazyflie_NO_NUMBERS_CROPPED).jpg‎|thumb|right|A high level overview of the Crazyflie Platform]] *[[PC Client Software]] *[[Firmware]] *[[USB Radio]] == Modifying the Platform == [[Image:SingleRadioMultiCrazyflie.jpg|thumb|right|A high level overview of the Swarm Platform we created]] *[[Controller]] *[[Logging]] *[[Keyboard Commands]] *[[USB Radio#Changing Radio Channel|Changing Radio Channel]] *[[Flight Modes]] *[[Callbacks]] *[[Adding a Crazyflie]] *[[:Firmware]] ==Future Project Ideas== The whole concept of this Platform is to constantly expand its capabilities. If you are interested in developing this platform further here are some ideas to get you started! Additional details on any of these ideas can be found on the [[Future Project Ideas]] page. *[[:Future Project Ideas#Migrating Swarm Client PID's to Firmware|Migrating Swarm Client PID's to Firmware]] *[[:Future Project Ideas#Model Development/Verification and Tuning X, Y, and Z Location PID's|Model Development/Verification and Tuning X, Y, and Z Location PID's]] *[[:Future Project Ideas#Adding Parameter Support to Swarm Client|Adding Parameter Support to Swarm Client]] *[[:Future Project Ideas#Threading Each USB Radio to speed up Computation|Threading Each USB Radio to speed up Computation]] *[[:Future Project Ideas#Developing New Controllers for the Crazyflie (pending Model Development)|Developing New Controllers for the Crazyflie (pending Model Development)]] *[[:Future Project Ideas#Develop Communications Network Between Crazyflies|Develop Communications Network Between Crazyflies]] *[[:Future Project Ideas#Trilateration Position Estimation using a Swarm|Trilateration Position Estimation using a Swarm]] == [https://wiki.bitcraze.io/ Bitcraze Wiki] == Bitcraze maintains their own wiki on the many Crazyflie systems. If you can't find what you are looking for here, chances are they will have something to help. a0d387286b6f276a370f5f1679b4b5b51d852570 File:MeasureVwheel.jpg 6 71 246 2016-08-02T20:00:49Z Pfuhing 5 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 File:PowerSplitter.jpg 6 72 250 2016-08-02T20:15:42Z Pfuhing 5 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Data Collection and Simulation Comparison 0 50 251 249 2016-08-02T20:21:53Z Pfuhing 5 /* Quad Battery */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another pop up window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation button'' - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to ''File->Save Trakables...'' and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packed drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have fond that even on a good strt the ''[ok]'' messages will still print. === Turing on RADA === Turing on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the swiches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you only the WIFI adapter or Ethernet plugged in at the same time or VRPN my listen to the camera data broadcast over both connects which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup with out needing to close the connection. If you are using a WIFI connect use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connaction use the command ''ssh root@192.168.0.54''. If the connection goes though you should be proped for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the first test after power up === For the firs test after powering on Eris a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect the the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell scrip will setup the NFS, load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject and runs the executable. Once the user exits the executable the log file produces is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see an warning that when coping the log file Eris couldn't maintain the file permisiion settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This Date stamp uses date on Eris which is currently in June of 2008 as of August 2nd, 2016. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA, you will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after start up you don't need to run this script. See the Section about Running additional tests below. [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode you can use the following commands to enter the desired mode with a three second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode, this will only really work when using PIDs to control the pendulum. -''b'' : Enter Robot control mode, in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode, where the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file incase odd things happen somewhere. This just increments a counter so if you use it look for changes in the marker value. ==== Robot Control Model ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box set mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use he same commands as Tuning Mode. === Running additional Tests === Once you have run one test with Eris on it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_stat_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result it is ready to test much quicker. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and retrieving log files === Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files are named like ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful of describing what the test was of or for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring battery voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there isn't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log is the headder. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value latter. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== 1. After test disconnect wheel battery from the system. 2. Measure voltage of battery using multimeter. [[Image:MeasureVwheel.jpg|800px]] You can use the plug used for charging the 2-cell Lipos but make sure to connect the plug to the multimeter before connecting the battery and disconnect the battery before disconnecting the plug from the mulitmeter. It is generally the best practice to give the multimeter a few minutes to allow for the voltage measurement to stabilize as the battery measurement tends to be a little low right after the test. ==== Quad Battery ==== 1. Setup code to run all four propellers at 50% throttle, uncomment the definition of ''mot50'' in main.cpp and compile the project. 2. Power off propellers by turning off the switch to the ESCs. 3. Connect multimeter to measure the voltage across one of the ESCs. This is done by using the power splitter cord. -Connect one of the female XT60 connectors on the splitter to a male XT60 connector to banana connector cable. -The banana connector connect to the hand held multimeter. The multimeter should be set to the 20VDC measurement setting. -Next unplug one the ESCs' power connection. -reconnect the ESC to power through the two remain connectors on the spliter cable. 4. Power on the propellers. 5. Run the system at 50% throttle and measure the steady-state voltage during the test. == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === be3dd8038f487120aa0034bbeefaad08af98a318 256 251 2016-08-02T20:49:37Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another pop up window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation button'' - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to ''File->Save Trakables...'' and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packed drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have fond that even on a good strt the ''[ok]'' messages will still print. === Turing on RADA === Turing on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the swiches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you only the WIFI adapter or Ethernet plugged in at the same time or VRPN my listen to the camera data broadcast over both connects which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup with out needing to close the connection. If you are using a WIFI connect use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connaction use the command ''ssh root@192.168.0.54''. If the connection goes though you should be proped for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the first test after power up === For the firs test after powering on Eris a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect the the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell scrip will setup the NFS, load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject and runs the executable. Once the user exits the executable the log file produces is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see an warning that when coping the log file Eris couldn't maintain the file permisiion settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This Date stamp uses date on Eris which is currently in June of 2008 as of August 2nd, 2016. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA, you will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after start up you don't need to run this script. See the Section about Running additional tests below. [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode you can use the following commands to enter the desired mode with a three second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode, this will only really work when using PIDs to control the pendulum. -''b'' : Enter Robot control mode, in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode, where the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file incase odd things happen somewhere. This just increments a counter so if you use it look for changes in the marker value. ==== Robot Control Model ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box set mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use he same commands as Tuning Mode. === Running additional Tests === Once you have run one test with Eris on it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_stat_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result it is ready to test much quicker. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and retrieving log files === Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files are named like ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful of describing what the test was of or for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring battery voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there isn't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log is the headder. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value latter. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== 1. After test disconnect wheel battery from the system. 2. Measure voltage of battery using multimeter. [[Image:MeasureVwheel.jpg|800px]] You can use the plug used for charging the 2-cell Lipos but make sure to connect the plug to the multimeter before connecting the battery and disconnect the battery before disconnecting the plug from the mulitmeter. It is generally the best practice to give the multimeter a few minutes to allow for the voltage measurement to stabilize as the battery measurement tends to be a little low right after the test. ==== Quad Battery ==== 1. Setup code to run all four propellers at 50% throttle, uncomment the definition of ''mot50'' in main.cpp and compile the project. 2. Power off propellers by turning off the switch to the ESCs. 3. Connect multimeter to measure the voltage across one of the ESCs. This is done by using the power splitter cord. -Connect one of the female XT60 connectors on the splitter to a male XT60 connector to banana connector cable. -The banana connector connect to the hand held multimeter. The multimeter should be set to the 20VDC measurement setting. -Next unplug one the ESCs' power connection. -reconnect the ESC to power through the two remain connectors on the spliter cable. 4. Power on the propellers. 5. Run the system at 50% throttle and measure the steady-state voltage during the test. {| class="wikitable" style="text-align:center" |- | [[Image:PowerSplitter.jpg|200px]] | [[Image:QuadMultiCon.jpg |200px]] | [[Image:QuadMultiSet.JPG |200px]] | [[Image:QuadMeasESCcon.JPG|200px]] |- | Splitter cord. | Connect splitter to multimeter. | Settings for multimeter. | Connecting ESC through splitter. |} == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === c043352430020dd172b243862477378e795c082c 257 256 2016-08-02T20:52:31Z Pfuhing 5 /* Quad Battery */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another pop up window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation button'' - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to ''File->Save Trakables...'' and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packed drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have fond that even on a good strt the ''[ok]'' messages will still print. === Turing on RADA === Turing on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the swiches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you only the WIFI adapter or Ethernet plugged in at the same time or VRPN my listen to the camera data broadcast over both connects which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup with out needing to close the connection. If you are using a WIFI connect use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connaction use the command ''ssh root@192.168.0.54''. If the connection goes though you should be proped for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the first test after power up === For the firs test after powering on Eris a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect the the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell scrip will setup the NFS, load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject and runs the executable. Once the user exits the executable the log file produces is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see an warning that when coping the log file Eris couldn't maintain the file permisiion settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This Date stamp uses date on Eris which is currently in June of 2008 as of August 2nd, 2016. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA, you will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after start up you don't need to run this script. See the Section about Running additional tests below. [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode you can use the following commands to enter the desired mode with a three second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode, this will only really work when using PIDs to control the pendulum. -''b'' : Enter Robot control mode, in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode, where the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file incase odd things happen somewhere. This just increments a counter so if you use it look for changes in the marker value. ==== Robot Control Model ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box set mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use he same commands as Tuning Mode. === Running additional Tests === Once you have run one test with Eris on it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_stat_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result it is ready to test much quicker. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and retrieving log files === Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files are named like ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful of describing what the test was of or for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring battery voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there isn't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log is the headder. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value latter. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== 1. After test disconnect wheel battery from the system. 2. Measure voltage of battery using multimeter. [[Image:MeasureVwheel.jpg|800px]] You can use the plug used for charging the 2-cell Lipos but make sure to connect the plug to the multimeter before connecting the battery and disconnect the battery before disconnecting the plug from the mulitmeter. It is generally the best practice to give the multimeter a few minutes to allow for the voltage measurement to stabilize as the battery measurement tends to be a little low right after the test. ==== Quad Battery ==== 1. Setup code to run all four propellers at 50% throttle, uncomment the definition of ''mot50'' in main.cpp and compile the project. 2. Power off propellers by turning off the switch to the ESCs. 3. Connect multimeter to measure the voltage across one of the ESCs. This is done by using the power splitter cord. -Connect one of the female XT60 connectors on the splitter to a male XT60 connector to banana connector cable. -The banana connector connect to the hand held multimeter. The multimeter should be set to the 20VDC measurement setting. -Next unplug one the ESCs' power connection. -reconnect the ESC to power through the two remain connectors on the spliter cable. 4. Power on the propellers. 5. Run the system at 50% throttle and measure the steady-state voltage during the test. The battery will slow the voltage decay significantly, meaning it will keep the same measurement for a few seconds. 6. Stop the test and record the voltage in the log file. {| class="wikitable" style="text-align:center" |- | [[Image:PowerSplitter.jpg|200px]] | [[Image:QuadMultiCon.jpg |200px]] | [[Image:QuadMultiSet.JPG |200px]] | [[Image:QuadMeasESCcon.JPG|200px]] |- | Splitter cord. | Connect splitter to multimeter. | Settings for multimeter. | Connecting ESC through splitter. |} The testing setup should look like the image below: [[Image:QuadBattMeas.jpg|800px]] == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === 17640831ca143a35cbb470248baf3558b5c90a1d 258 257 2016-08-02T20:53:47Z Pfuhing 5 /* Quad Battery */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another pop up window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation button'' - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to ''File->Save Trakables...'' and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packed drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have fond that even on a good strt the ''[ok]'' messages will still print. === Turing on RADA === Turing on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the swiches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you only the WIFI adapter or Ethernet plugged in at the same time or VRPN my listen to the camera data broadcast over both connects which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup with out needing to close the connection. If you are using a WIFI connect use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connaction use the command ''ssh root@192.168.0.54''. If the connection goes though you should be proped for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the first test after power up === For the firs test after powering on Eris a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect the the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell scrip will setup the NFS, load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject and runs the executable. Once the user exits the executable the log file produces is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see an warning that when coping the log file Eris couldn't maintain the file permisiion settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This Date stamp uses date on Eris which is currently in June of 2008 as of August 2nd, 2016. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA, you will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after start up you don't need to run this script. See the Section about Running additional tests below. [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode you can use the following commands to enter the desired mode with a three second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode, this will only really work when using PIDs to control the pendulum. -''b'' : Enter Robot control mode, in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode, where the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file incase odd things happen somewhere. This just increments a counter so if you use it look for changes in the marker value. ==== Robot Control Model ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box set mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use he same commands as Tuning Mode. === Running additional Tests === Once you have run one test with Eris on it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_stat_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result it is ready to test much quicker. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and retrieving log files === Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files are named like ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful of describing what the test was of or for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring battery voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there isn't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log is the headder. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value latter. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== 1. After test disconnect wheel battery from the system. 2. Measure voltage of battery using multimeter. [[Image:MeasureVwheel.jpg|800px]] You can use the plug used for charging the 2-cell Lipos but make sure to connect the plug to the multimeter before connecting the battery and disconnect the battery before disconnecting the plug from the mulitmeter. It is generally the best practice to give the multimeter a few minutes to allow for the voltage measurement to stabilize as the battery measurement tends to be a little low right after the test. ==== Quad Battery ==== 1. Setup code to run all four propellers at 50% throttle, uncomment the definition of ''mot50'' in main.cpp and compile the project. 2. Power off propellers by turning off the switch to the ESCs. 3. Connect multimeter to measure the voltage across one of the ESCs. This is done by using the power splitter cord. -Connect one of the female XT60 connectors on the splitter to a male XT60 connector to banana connector cable. -The banana connector connect to the hand held multimeter. The multimeter should be set to the 20VDC measurement setting. -Next unplug one the ESCs' power connection. -reconnect the ESC to power through the two remain connectors on the spliter cable. 4. Power on the propellers. 5. Run the system at 50% throttle and measure the steady-state voltage during the test. The battery will slow the voltage decay significantly, meaning it will keep the same measurement for a few seconds. 6. Stop the test and record the voltage in the log file. Make sure to disconnect the batter before removing the splitter cable. {| class="wikitable" style="text-align:center" |- | [[Image:PowerSplitter.jpg|200px]] | [[Image:QuadMultiCon.jpg |200px]] | [[Image:QuadMultiSet.JPG |200px]] | [[Image:QuadMeasESCcon.JPG|200px]] |- | Splitter cord. | Connect splitter to multimeter. | Settings for multimeter. | Connecting ESC through splitter. |} The testing setup should look like the image below: [[Image:QuadBattMeas.jpg|800px]] == Post processing and Simulation == === Using the MATLAB data parsing tool === === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === 75b928c12401e94896f3814a9dbf0ca80c16aca2 259 258 2016-08-02T21:02:14Z Pfuhing 5 /* Post processing and Simulation */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another pop up window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation button'' - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to ''File->Save Trakables...'' and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packed drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have fond that even on a good strt the ''[ok]'' messages will still print. === Turing on RADA === Turing on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the swiches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you only the WIFI adapter or Ethernet plugged in at the same time or VRPN my listen to the camera data broadcast over both connects which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup with out needing to close the connection. If you are using a WIFI connect use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connaction use the command ''ssh root@192.168.0.54''. If the connection goes though you should be proped for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the first test after power up === For the firs test after powering on Eris a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect the the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell scrip will setup the NFS, load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject and runs the executable. Once the user exits the executable the log file produces is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see an warning that when coping the log file Eris couldn't maintain the file permisiion settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This Date stamp uses date on Eris which is currently in June of 2008 as of August 2nd, 2016. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA, you will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after start up you don't need to run this script. See the Section about Running additional tests below. [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode you can use the following commands to enter the desired mode with a three second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode, this will only really work when using PIDs to control the pendulum. -''b'' : Enter Robot control mode, in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode, where the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file incase odd things happen somewhere. This just increments a counter so if you use it look for changes in the marker value. ==== Robot Control Model ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box set mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use he same commands as Tuning Mode. === Running additional Tests === Once you have run one test with Eris on it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_stat_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result it is ready to test much quicker. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and retrieving log files === Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files are named like ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful of describing what the test was of or for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring battery voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there isn't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log is the headder. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value latter. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== 1. After test disconnect wheel battery from the system. 2. Measure voltage of battery using multimeter. [[Image:MeasureVwheel.jpg|800px]] You can use the plug used for charging the 2-cell Lipos but make sure to connect the plug to the multimeter before connecting the battery and disconnect the battery before disconnecting the plug from the mulitmeter. It is generally the best practice to give the multimeter a few minutes to allow for the voltage measurement to stabilize as the battery measurement tends to be a little low right after the test. ==== Quad Battery ==== 1. Setup code to run all four propellers at 50% throttle, uncomment the definition of ''mot50'' in main.cpp and compile the project. 2. Power off propellers by turning off the switch to the ESCs. 3. Connect multimeter to measure the voltage across one of the ESCs. This is done by using the power splitter cord. -Connect one of the female XT60 connectors on the splitter to a male XT60 connector to banana connector cable. -The banana connector connect to the hand held multimeter. The multimeter should be set to the 20VDC measurement setting. -Next unplug one the ESCs' power connection. -reconnect the ESC to power through the two remain connectors on the spliter cable. 4. Power on the propellers. 5. Run the system at 50% throttle and measure the steady-state voltage during the test. The battery will slow the voltage decay significantly, meaning it will keep the same measurement for a few seconds. 6. Stop the test and record the voltage in the log file. Make sure to disconnect the batter before removing the splitter cable. {| class="wikitable" style="text-align:center" |- | [[Image:PowerSplitter.jpg|200px]] | [[Image:QuadMultiCon.jpg |200px]] | [[Image:QuadMultiSet.JPG |200px]] | [[Image:QuadMeasESCcon.JPG|200px]] |- | Splitter cord. | Connect splitter to multimeter. | Settings for multimeter. | Connecting ESC through splitter. |} The testing setup should look like the image below: [[Image:QuadBattMeas.jpg|800px]] == Post processing and Simulation == Simulating a test of RADA starts with processing and storing the data. Then all of the parameters of the model are loaded in the MATLAB Workspace. Finally the Simulink file used for the simulation is opened and the length of the simulation is set to match the length of the actual test. The simulation is run and the simulation output is stored. Finally the data should be plotted and compared. === Using the MATLAB data parsing tool === In depth discussion of how to use the log file parsing tool is described === Adding additional data for simulations === === Setting up the MATLAB workspace for simulation === === Running simulations and storing results === === Plotting results === 787010c4f2fa74d9cba33fb619594f6450f212de 260 259 2016-08-02T22:16:44Z Pfuhing 5 wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. The initial setup and how to test the system can also be applied to demoing RADA. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another pop up window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation button'' - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to ''File->Save Trakables...'' and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packed drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have fond that even on a good strt the ''[ok]'' messages will still print. === Turing on RADA === Turing on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the swiches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you only the WIFI adapter or Ethernet plugged in at the same time or VRPN my listen to the camera data broadcast over both connects which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup with out needing to close the connection. If you are using a WIFI connect use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connaction use the command ''ssh root@192.168.0.54''. If the connection goes though you should be proped for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the first test after power up === For the firs test after powering on Eris a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect the the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell scrip will setup the NFS, load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject and runs the executable. Once the user exits the executable the log file produces is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see an warning that when coping the log file Eris couldn't maintain the file permisiion settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This Date stamp uses date on Eris which is currently in June of 2008 as of August 2nd, 2016. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA, you will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after start up you don't need to run this script. See the Section about Running additional tests below. [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode you can use the following commands to enter the desired mode with a three second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode, this will only really work when using PIDs to control the pendulum. -''b'' : Enter Robot control mode, in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode, where the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file incase odd things happen somewhere. This just increments a counter so if you use it look for changes in the marker value. ==== Robot Control Model ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box set mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use he same commands as Tuning Mode. === Running additional Tests === Once you have run one test with Eris on it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_stat_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result it is ready to test much quicker. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and retrieving log files === If you are only demoing the system there is no need to go beyond this point. Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files are named like ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful of describing what the test was of or for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring battery voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there isn't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log is the headder. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value latter. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== 1. After test disconnect wheel battery from the system. 2. Measure voltage of battery using multimeter. [[Image:MeasureVwheel.jpg|800px]] You can use the plug used for charging the 2-cell Lipos but make sure to connect the plug to the multimeter before connecting the battery and disconnect the battery before disconnecting the plug from the mulitmeter. It is generally the best practice to give the multimeter a few minutes to allow for the voltage measurement to stabilize as the battery measurement tends to be a little low right after the test. The multimeter will report data out to four decimal places it is best just to round to three decimal places for the wheel voltage. ==== Quad Battery ==== 1. Setup code to run all four propellers at 50% throttle, uncomment the definition of ''mot50'' in main.cpp and compile the project. 2. Power off propellers by turning off the switch to the ESCs. 3. Connect multimeter to measure the voltage across one of the ESCs. This is done by using the power splitter cord. -Connect one of the female XT60 connectors on the splitter to a male XT60 connector to banana connector cable. -The banana connector connect to the hand held multimeter. The multimeter should be set to the 20VDC measurement setting. -Next unplug one the ESCs' power connection. -reconnect the ESC to power through the two remain connectors on the spliter cable. 4. Power on the propellers. 5. Run the system at 50% throttle and measure the steady-state voltage during the test. The battery will slow the voltage decay significantly, meaning it will keep the same measurement for a few seconds. 6. Stop the test and record the voltage in the log file. Make sure to disconnect the batter before removing the splitter cable. {| class="wikitable" style="text-align:center" |- | [[Image:PowerSplitter.jpg|200px]] | [[Image:QuadMultiCon.jpg |200px]] | [[Image:QuadMultiSet.JPG |200px]] | [[Image:QuadMeasESCcon.JPG|200px]] |- | Splitter cord. | Connect splitter to multimeter. | Settings for multimeter. | Connecting ESC through splitter. |} The testing setup should look like the image below: [[Image:QuadBattMeas.jpg|800px]] == Post processing and Simulation == Simulating a test of RADA starts with processing and storing the data. Then all of the parameters of the model are loaded in the MATLAB Workspace. Finally the Simulink file used for the simulation is opened and the length of the simulation is set to match the length of the actual test. The simulation is run and the simulation output is stored. Finally the data should be plotted and compared. === Using the MATLAB data parsing tool === In depth discussion of how to use the log file parsing tool is described [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] I suggest using the version of the tool in the rada_resarch_project git repository Paul Uhing used for his Master's research. It con be found on CO3050-11 under the ucart account in the directory ''~/rada_research_project/DataAnalysiTool_omnicoor/Tool''. Simply open MATLAB and set the working directory to this file path. In the MATLAB Command Prompt run ''DataAnalysis''. A popup window should open up. Select the log file you want to process and wait for the tool to finish processing the file. Once this is complete there should be four structures in the MATLAB workspace. -'''main''' : This contains all of the data extracted from the log file and the processing parameters used. main.expData contains two time structures: Time is used for the pendulum data and Eris_time is used for the ground vehicle data. -'''X_ref''' : This contains the reference vector in m/s for x velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Y_ref''' : This contains the reference vector in m/s for y velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Yaw_ref''' : This contains the reference vector in radians for yaw that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. This one is new incase people start testing the system with heading changes but is not used in the current setup. The first thing you should do is rename the main structure to the name you used for the log file. This is helpful for comparing multiple tests. Next you will want to crate two new variable ''Vquad_test'' an Vw_test''. In the MATLAB Command Prompt set the measured propeller voltage from the log file to ''Vquad_test'' and set the measured the wheel voltage to ''Vw_test'' as this will be used by the simulation. Finally if you did an open-loop test of the wheels create the variable ''Uol'' and set it to the open-loop wheel command used. Save all of these variables from the MATLAB workspace to a ''.mat'' file of the same name as log file you extracted the data from and save it in the same directory as your RADA Simulink files. As of August 2nd, 2016 this directory is ''~/rada_research_project/MATLAB/RADA.'' === Setting up the MATLAB workspace for simulation === Change your MATLAB directory to this directory. Then run the simulation setup files. Currently you just need to run ''modelParams_smallWheels_RADA'' in the MATLAB Command Prompt. Next open the Simulink file with that contains the model of RADA controlled by the controller you tested. -'''RADA_psiCtrl_v2_lqi_est.slx''' contains LQI, LQI+estimation, and LQG controller simulations. -'''RADA_psiCtrl_v2.slx''' contains the PID controlled system. -'''RADA_psiCtrl_v2_LQGsep.slx''' contains the subsystem LQG controlled system. -'''RADA_psiCtrl_v2_LQGsep_ol.slx''' contains the simulation of the pendulum system controlled by an LQG and Eris controlled with open-loop commands. Note all of the current (August 2nd, 2016) ''.slx'' files were created in MATLAB 2014b and will only work in MATLAB 2014B or newer. Then in the MATLAB Command Prompt type ''X_ref.time(end)'' exactly, don't add a semicolon, and hit enter. MATLAB will print the time of the last command in the X_ref structure. Set the en time of the simulation to this value and save your Simulink file. === Running simulations and storing results === Before running the simulation make sure that the simuation is using the ''ode23t'' differential equations solver. This system is a moderately stiff system of differential and the ''ode45'' solver doesn't do well with these types of systems. When using ''ode23t'' is should only take a few minutes to run a 100+ second simulation while doing the same test using ''ode45'' could take 8 hours. While this slow it is also bad for your hard drive as the simulation has to page between RAM and your computers hard drive a lot. Once this check is done run the simulation. While it is running check what the output structures variables are named for for your RADA test system. Once the simulation is done go to your MATLAB Workspace and select all 15 outputs for your simulation or your sub-simulation if you used '''RADA_psiCtrl_v2_lqi_est.slx'''. Save these 15 output structures to a ''.mat'' file named as the log file with _sim appended to the end of the name. The 15 outputs are structures containing a time vector and then the data from the simulation sampled at 100 Hz and the units of this data are the SI units (ex: radians, m/s). There is one output structure for x velocity, y velocity, x body velocity, y body velocity, theta (pitch), phi (roll), psi (yaw), and one per actuator command (ex: the command sent to a wheel). Now you have all the data you can plot it. === Plotting results === If you look at the ''DataSets'' folder below ''~/rada_research_project/MATLAB/RADA'' directory there are plenty of examples of how Paul Uhing compared simulation to test data. Generally you should grate a ''.m'' file with the same name as the log file this data was extracted from with _plot appended to the name. Generally you can just copy an for RADA_LQG_compPID_plot.m RADA_PID_compLQG_plot.m, RADA_LQG_sep_plot.m, or RADA_LQG_sep_ol_plot.m files and rename the structures for your test. These files create four figures. Figure 1 plots compares the x velocity data in the first sub figure and compares pitch (theta) data in the second sub figure. Figure 2 does the same thing as Figure 1 but with y velocity and roll data. Figure 3 looks at the yaw data. Finally, Figure 4 looks at the sample period between UAV and ERIS packets from the camera system just to check for periods of time with large packet drops. You can follow a similar pattern to compare motor commands. Just make sure that you compare Quad Motor 2 from the test data with Quad Motor 4 from simulation and vise versa because propellers 2 and 4 were switch in Eris's software compared to the Model. That is all you need to know for testing RADA against the model. 5cbea2030b7bfce659c60008efa0777adae3e80d File:QuadBattMeas.jpg 6 73 252 2016-08-02T20:42:10Z Pfuhing 5 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 File:QuadMultiSet.JPG 6 74 253 2016-08-02T20:42:52Z Pfuhing 5 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 File:QuadMultiCon.jpg 6 75 254 2016-08-02T20:43:28Z Pfuhing 5 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 File:QuadMeasESCcon.JPG 6 76 255 2016-08-02T20:44:09Z Pfuhing 5 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 File:TrackingToolsOpenTrackables.PNG 6 77 261 2016-08-03T16:12:35Z Jnoronha 3 Crazyflie constellation trackables in camera system wikitext text/x-wiki Crazyflie constellation trackables in camera system c5c6415777f985d27fd47294431c09cfea92f639 299 261 2016-08-27T17:50:55Z Jnoronha 3 Jnoronha uploaded a new version of [[File:TrackingToolsOpenTrackables.PNG]] wikitext text/x-wiki Crazyflie constellation trackables in camera system c5c6415777f985d27fd47294431c09cfea92f639 File:CrazyflieLocationLayoutAnnotated.png 6 78 262 2016-08-03T16:44:13Z Jnoronha 3 Crazyflie layout in the Camera field of view wikitext text/x-wiki Crazyflie layout in the Camera field of view b1f50fd263a0e7c21941c230fd9d027f07302dd2 File:CrazyflieLocationLayoutAnnotatedSmall.png 6 79 263 2016-08-03T16:53:18Z Jnoronha 3 Crazyflie location and orientation in the Camera system field of view wikitext text/x-wiki Crazyflie location and orientation in the Camera system field of view 042911874ff40ae34740dad4b5a70f2c992253f5 298 263 2016-08-27T17:48:57Z Jnoronha 3 Jnoronha uploaded a new version of [[File:CrazyflieLocationLayoutAnnotatedSmall.png]] wikitext text/x-wiki Crazyflie location and orientation in the Camera system field of view 042911874ff40ae34740dad4b5a70f2c992253f5 PC Client Software 0 25 264 224 2016-08-03T16:57:34Z Jnoronha 3 /* Swarm Client */ added vrpn images for running the swarm client wikitext text/x-wiki The PC Client software comes in many forms. The out-of-the-box Client is written in Python and has a Graphical User Interface (GUI). The GUI is well suited for beginners, but can only support a single Radio and a single Crazyflie at a time. The easiest way to start out is with the [https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze Virtual Machine (VM)], which comes with all the files and dependencies pre-installed and can run on any computer (Windows, Mac, Linux, etc.). For more advanced users who want to use the swarm capabilities of our platform will have to use the [[#Swarm Client|Swarm Client]] we developed in C and C++. ==[https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze VM]== ('''Note:''' The VM is updated frequently so the information below may be different than the current VM) The Bitcraze wiki has a tutorial on [https://wiki.bitcraze.io/projects:virtualmachine:tutorials:vmware-win7 installing the VM]. Along with another tutorial on how to get started [https://www.bitcraze.io/getting-started-with-development/ using the VM]. These are both very simple starting guides that will help you become familiar with the VM. ===Crazyflie Client GUI=== On the VM you can find the Crazyflie Client Graphical User Interface (GUI). To run the Client you want to open a terminal and navigate to <code>/home/bitcraze/Desktop/projects/crazyflie-clients-python/</code> and then run the command <code>sudo ./bin/cfclient</code> (Alternatively, you can use the desktop to navigate to the folder and open a terminal there) Once you do that you should see something similar to this: [[Image:DefaultCrazyflieGUIMainScreen.JPG|500px]] This is the main screen of the Client GUI and there are many tabs and features that you can access directly from this screen. The most important parts of this screen are the following: #Connect Button #Bootloader (Crazyflie Drop Down -> Bootloader) #Plotter Tab #Log Blocks Tab #Parameters Tab ====Connect Button==== This is where you will scan for Crazyflies that are powered ON. All Crazyflies not already connected will show up in the popup [[Image:DefaultCrazyflieGUIConnectScreen.JPG|400px]] We get a return that says <code>radio://0/45/2M</code>, this line is the identifier string of the Crazyflie we are trying to connect to. What this is saying is that we got a return from: #Radio 0 (the first radio) #Crazyflie on Channel 45 #Using a data rate of 2Mbps ====Bootloader==== This where you can install new Firmware to the Crazyflie. [[Image:DefaultCrazyflieGUIBootloader.JPG|500px]] The first thing you'll need to update is to build the Firmware version you want into a .bin file. You can do this by just running the <code>make</code> command in terminal while located inside the Firmware directory you have modified. Once you have that .bin file built you: #Open the bootloader shown #Hold down the power button on the Crazyflie 2.0 for around 3 seconds until the 2 blue LED's flash and alternate. This puts the Crazyflie in bootloader mode. ('''NOTE:''' Recommend having '''ALL other Crazyflies OFF''' or else it could accidentally flash both Crazyflies.) #Then hit ''Initiate bootloader cold boot'' (it should connect to the Crazyflie in bootloader mode after a few seconds, Status will change from 'Not Connected' to 'Connected') #Hit ''Browse'' and find the .bin file you built earlier. #Then click ''Program'' and wait for the progress bar to complete. #Restart the Crazyflie in Firmware mode and make sure it starts up normally, if something seems wrong just repeat steps 2 through 6 again. ====Logging Tab==== Once you connect to a Crazyflie you can monitor certain log variables that have been set up. You will see a plot of the data similar to this: [[Image:DefaultCrazyflieGUILoggerScreen.JPG|400px]] On this screen we can do the following things: *Dropdown Menu at the top of the screen **Select which log block you want to plot on screen. *Scale the X-axis of the plot by: **Range **Number of Samples **Time in Seconds **Manually *Scale the Y-axis by: **Automatically **Manual Range ====Parameters Tab==== This tab displays all the parameters currently set up on the Crazyflie Firmware. Once you connect to a Crazyflie it lists these parameters in a table format similar to below: [[Image:DefaultCrazyflieGUIParametersScreen.JPG|400px]] For each parameter we get its Name, Variable Type, Access Type (Read/Write), and its Current Value. We can also modify the parameter values on this screen in real-time and the changes will be sent to the Crazyflie automatically. ('''Note:''' Any parameter changes made on this screen are NOT preserved when you turn OFF the Crazyflie.) ==Swarm Client== The swarm Client is a re-creation of the Original Client but programmed in C and C++. The benefit of this is that *We use a unified language between Client and Firmware *Easily migrate this platform to any linux distribution that can install the Crazyflie dependencies. **Our platform code itself requires only the VRPN libraries and a generic C compiler. ===Using the Swarm Client=== The Swarm Client uses the terminal interface for User Input. [[Image:CrazyflieTerminalInitial.png|400px]] Here we see what the initial Terminal looks like before we do anything. :1. The first thing you want to do before any testing is to run the <code>sudo make</code> command in the Swarm Client directory. (Yes, the 'sudo' is necessary) ::This will make sure you have all the necessary dependencies, that the code is error free, and then it will build an executable (.exe) file of the Swarm Client code. An error free make will look something like this: ::[[Image:CrazyflieTerminalPostMake.png|400px]] ::There will be warnings, but those don't cause any issues right now. :2. Pre-Test Checklist ::*Camera System is Turned on and Crazyflie Trackables are opened and visible. :::[[Image:TrackingToolsOpenTrackables.PNG|400px]] [[Image:TrackingToolsCrazyflieConstellationZeroing.png|400px]] ::*Radios are plugged into the USB Ports on the Client computer. ::*Crazyflies are ON and NOT in an Error State. ::**'''IMPORTANT!!!''' Face Crazyflie 'Nose' (Red Dot in picture) towards the East wall when powering ON! (to synch yaw correctly) :::[[Image:CrazyflieLocationLayoutAnnotatedSmall.png|500px]] :3. Run the executable file using the command <code>sudo ./eris_vrpn</code> in the same directory (Yes, the 'sudo' is necessary). This will start the program initialization and a bunch of status info will flood the screen. You will know the program is ready for input when you see the following: ::[[Image:CrazyflieTerminalProgramStarted.png|400px]] ::This means that the Crazyflie yaw has been synchronized with the Camera system and they are ready to fly. :4. Input a Keyboard Command ::This will depend on what you have programmed as the keyboard input commands. As of 7/19/16 we have the following Keyboard Commands active: ::*'1' - Rotates Yaw of Crazyflie1 +45 degrees ::*'2' - Rotates Yaw of Crazyflie1 -45 degrees ::*'q' - Ends Main Loop (OBSOLETE - Replaced with ctrl + c) ::*'e' - Landing Mode (for ALL Crazyflies) ::*'t' - Crazyflie1 Take-Off ::*'y' - Crazyflie2 Take-Off ::*'u' - Crazyflie3 Take-Off ::*'i' - Crazyflie4 Take-Off ::*'h' - Hand Gesture Mode (for ALL Crazyflies) ::*'m' - Mirror Mode (for ALL Crazyflies) ::*ctrl+c - Quits Program, performs all cleanup. ::An example of what this would look like in the Terminal is shown here: ::[[Image:CrazyflieTerminalKeyboardInput.png|400px]] ::So you can see we commanded all 4 Crazyflies to take off (t,y,u,i), then activated Landing Mode (e), then activated Hand Mode (h), and then Ended the Program (ctrl+c). :5. End Program when finished (ctrl+c) ::This will end the program loop, print the current battery levels, and Delete the Radio pointers (shown at the end of the previous figure) ===Makefile=== The Swarm Client is compiled by a simple makefile. So when you call ''sudo make'' this makefile converts the C++ code files into an executable (.exe) for us. <blockquote> <code> <pre> g++ = g++ -Wall all: eris_vrpn eris_vrpn: eris_vrpn.h eris_vrpn.cpp vrpn.h vrpn.cpp CCrazyflie.h CCrazyflie.cpp CCrazyRadio.h CCrazyRadio.cpp CCRTPPacket.h CCRTPPacket.cpp CTOC.h CTOC.cpp simple.cpp simple.h pid.h pid.c controller.h controller.c multicast.c $(g++) -g -O0 -o eris_vrpn eris_vrpn.cpp vrpn.cpp CCrazyflie.cpp CCrazyRadio.cpp CCRTPPacket.cpp CTOC.cpp simple.cpp pid.c controller.c multicast.c -lquat -lvrpn -lpthread -lusb-1.0 clean: rm -f *.o eris_vrpn </pre> </code> </blockquote> ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 18fc8b4ae2b769b12c7090e3c905f41984429db5 265 264 2016-08-03T16:58:29Z Jnoronha 3 added spacing between major sections wikitext text/x-wiki The PC Client software comes in many forms. The out-of-the-box Client is written in Python and has a Graphical User Interface (GUI). The GUI is well suited for beginners, but can only support a single Radio and a single Crazyflie at a time. The easiest way to start out is with the [https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze Virtual Machine (VM)], which comes with all the files and dependencies pre-installed and can run on any computer (Windows, Mac, Linux, etc.). For more advanced users who want to use the swarm capabilities of our platform will have to use the [[#Swarm Client|Swarm Client]] we developed in C and C++. ==[https://wiki.bitcraze.io/projects:virtualmachine:index Bitcraze VM]== ('''Note:''' The VM is updated frequently so the information below may be different than the current VM) The Bitcraze wiki has a tutorial on [https://wiki.bitcraze.io/projects:virtualmachine:tutorials:vmware-win7 installing the VM]. Along with another tutorial on how to get started [https://www.bitcraze.io/getting-started-with-development/ using the VM]. These are both very simple starting guides that will help you become familiar with the VM. ===Crazyflie Client GUI=== On the VM you can find the Crazyflie Client Graphical User Interface (GUI). To run the Client you want to open a terminal and navigate to <code>/home/bitcraze/Desktop/projects/crazyflie-clients-python/</code> and then run the command <code>sudo ./bin/cfclient</code> (Alternatively, you can use the desktop to navigate to the folder and open a terminal there) Once you do that you should see something similar to this: [[Image:DefaultCrazyflieGUIMainScreen.JPG|500px]] This is the main screen of the Client GUI and there are many tabs and features that you can access directly from this screen. The most important parts of this screen are the following: #Connect Button #Bootloader (Crazyflie Drop Down -> Bootloader) #Plotter Tab #Log Blocks Tab #Parameters Tab ====Connect Button==== This is where you will scan for Crazyflies that are powered ON. All Crazyflies not already connected will show up in the popup [[Image:DefaultCrazyflieGUIConnectScreen.JPG|400px]] We get a return that says <code>radio://0/45/2M</code>, this line is the identifier string of the Crazyflie we are trying to connect to. What this is saying is that we got a return from: #Radio 0 (the first radio) #Crazyflie on Channel 45 #Using a data rate of 2Mbps ====Bootloader==== This where you can install new Firmware to the Crazyflie. [[Image:DefaultCrazyflieGUIBootloader.JPG|500px]] The first thing you'll need to update is to build the Firmware version you want into a .bin file. You can do this by just running the <code>make</code> command in terminal while located inside the Firmware directory you have modified. Once you have that .bin file built you: #Open the bootloader shown #Hold down the power button on the Crazyflie 2.0 for around 3 seconds until the 2 blue LED's flash and alternate. This puts the Crazyflie in bootloader mode. ('''NOTE:''' Recommend having '''ALL other Crazyflies OFF''' or else it could accidentally flash both Crazyflies.) #Then hit ''Initiate bootloader cold boot'' (it should connect to the Crazyflie in bootloader mode after a few seconds, Status will change from 'Not Connected' to 'Connected') #Hit ''Browse'' and find the .bin file you built earlier. #Then click ''Program'' and wait for the progress bar to complete. #Restart the Crazyflie in Firmware mode and make sure it starts up normally, if something seems wrong just repeat steps 2 through 6 again. ====Logging Tab==== Once you connect to a Crazyflie you can monitor certain log variables that have been set up. You will see a plot of the data similar to this: [[Image:DefaultCrazyflieGUILoggerScreen.JPG|400px]] On this screen we can do the following things: *Dropdown Menu at the top of the screen **Select which log block you want to plot on screen. *Scale the X-axis of the plot by: **Range **Number of Samples **Time in Seconds **Manually *Scale the Y-axis by: **Automatically **Manual Range ====Parameters Tab==== This tab displays all the parameters currently set up on the Crazyflie Firmware. Once you connect to a Crazyflie it lists these parameters in a table format similar to below: [[Image:DefaultCrazyflieGUIParametersScreen.JPG|400px]] For each parameter we get its Name, Variable Type, Access Type (Read/Write), and its Current Value. We can also modify the parameter values on this screen in real-time and the changes will be sent to the Crazyflie automatically. ('''Note:''' Any parameter changes made on this screen are NOT preserved when you turn OFF the Crazyflie.) ==Swarm Client== The swarm Client is a re-creation of the Original Client but programmed in C and C++. The benefit of this is that *We use a unified language between Client and Firmware *Easily migrate this platform to any linux distribution that can install the Crazyflie dependencies. **Our platform code itself requires only the VRPN libraries and a generic C compiler. ===Using the Swarm Client=== The Swarm Client uses the terminal interface for User Input. [[Image:CrazyflieTerminalInitial.png|400px]] Here we see what the initial Terminal looks like before we do anything. :1. The first thing you want to do before any testing is to run the <code>sudo make</code> command in the Swarm Client directory. (Yes, the 'sudo' is necessary) ::This will make sure you have all the necessary dependencies, that the code is error free, and then it will build an executable (.exe) file of the Swarm Client code. An error free make will look something like this: ::[[Image:CrazyflieTerminalPostMake.png|400px]] ::There will be warnings, but those don't cause any issues right now. :2. Pre-Test Checklist ::*Camera System is Turned on and Crazyflie Trackables are opened and visible. :::[[Image:TrackingToolsOpenTrackables.PNG|400px]] [[Image:TrackingToolsCrazyflieConstellationZeroing.png|400px]] ::*Radios are plugged into the USB Ports on the Client computer. ::*Crazyflies are ON and NOT in an Error State. ::**'''IMPORTANT!!!''' Face Crazyflie 'Nose' (Red Dot in picture) towards the East wall when powering ON! (to synch yaw correctly) :::[[Image:CrazyflieLocationLayoutAnnotatedSmall.png|500px]] :3. Run the executable file using the command <code>sudo ./eris_vrpn</code> in the same directory (Yes, the 'sudo' is necessary). This will start the program initialization and a bunch of status info will flood the screen. You will know the program is ready for input when you see the following: ::[[Image:CrazyflieTerminalProgramStarted.png|400px]] ::This means that the Crazyflie yaw has been synchronized with the Camera system and they are ready to fly. :4. Input a Keyboard Command ::This will depend on what you have programmed as the keyboard input commands. As of 7/19/16 we have the following Keyboard Commands active: ::*'1' - Rotates Yaw of Crazyflie1 +45 degrees ::*'2' - Rotates Yaw of Crazyflie1 -45 degrees ::*'q' - Ends Main Loop (OBSOLETE - Replaced with ctrl + c) ::*'e' - Landing Mode (for ALL Crazyflies) ::*'t' - Crazyflie1 Take-Off ::*'y' - Crazyflie2 Take-Off ::*'u' - Crazyflie3 Take-Off ::*'i' - Crazyflie4 Take-Off ::*'h' - Hand Gesture Mode (for ALL Crazyflies) ::*'m' - Mirror Mode (for ALL Crazyflies) ::*ctrl+c - Quits Program, performs all cleanup. ::An example of what this would look like in the Terminal is shown here: ::[[Image:CrazyflieTerminalKeyboardInput.png|400px]] ::So you can see we commanded all 4 Crazyflies to take off (t,y,u,i), then activated Landing Mode (e), then activated Hand Mode (h), and then Ended the Program (ctrl+c). :5. End Program when finished (ctrl+c) ::This will end the program loop, print the current battery levels, and Delete the Radio pointers (shown at the end of the previous figure) ===Makefile=== The Swarm Client is compiled by a simple makefile. So when you call ''sudo make'' this makefile converts the C++ code files into an executable (.exe) for us. <blockquote> <code> <pre> g++ = g++ -Wall all: eris_vrpn eris_vrpn: eris_vrpn.h eris_vrpn.cpp vrpn.h vrpn.cpp CCrazyflie.h CCrazyflie.cpp CCrazyRadio.h CCrazyRadio.cpp CCRTPPacket.h CCRTPPacket.cpp CTOC.h CTOC.cpp simple.cpp simple.h pid.h pid.c controller.h controller.c multicast.c $(g++) -g -O0 -o eris_vrpn eris_vrpn.cpp vrpn.cpp CCrazyflie.cpp CCrazyRadio.cpp CCRTPPacket.cpp CTOC.cpp simple.cpp pid.c controller.c multicast.c -lquat -lvrpn -lpthread -lusb-1.0 clean: rm -f *.o eris_vrpn </pre> </code> </blockquote> ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 2aafe7e6665dc99268922ebede8235d6d081581e FAQ 0 40 266 244 2016-08-03T17:03:40Z Jnoronha 3 added question 6 wikitext text/x-wiki Here you can find some Frequently Asked Questions: :'''1. How do I change the Radio Channel?''' ::Find out here: [[:USB Radio#Changing Radio Channel|Changing the Radio Channel]] :'''2. How do I use Log Blocks?''' ::*Creating and using [[:Logging#Client-Side External Log Files|External Client-side Log Files]] ::*Creating [[:Firmware#New Firmware Log Blocks|New Log Blocks in Firmware]] ::*Creating and Using [[:Logging#New Client Log Blocks|New Log Blocks in Client]] :'''3. I just want to run the code, how do I run it?''' ::See [[:PC Client Software#Using the Swarm Client|Using the Swarm Client]] :'''4. What are the Keyboard Commands for flying the Crazyflie?''' ::You can find a full list of all the Key Commands in [[:Keyboard Commands]] ::(Alternatively: See '''Step 4''' of [[:PC Client Software#Using the Swarm Client|Using the Swarm Client]]) :'''5. How do I plot the Log Files that the Crazyflie Swarm Creates?''' ::See the [[:Logging#MATLAB Parser|MATLAB Parser]] section for examples. :'''6. Can I change what files are compiled during <code>make</code>?''' ::Yep! You need to modify the makefile in the Client directory. Follow the example shown [[:PC Client Software#Makefile|here]]. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 3fc08456cdd2222fd5a08d6e06b57f8f711421e5 267 266 2016-08-03T17:06:19Z Jnoronha 3 bolded links wikitext text/x-wiki Here you can find some Frequently Asked Questions: :'''1. How do I change the Radio Channel?''' ::Find out here: '''[[:USB Radio#Changing Radio Channel|Changing the Radio Channel]]''' :'''2. How do I use Log Blocks?''' ::*Creating and using '''[[:Logging#Client-Side External Log Files|External Client-side Log Files]]''' ::*Creating '''[[:Firmware#New Firmware Log Blocks|New Log Blocks in Firmware]]''' ::*Creating and Using '''[[:Logging#New Client Log Blocks|New Log Blocks in Client]]''' :'''3. I just want to run the code, how do I run it?''' ::See '''[[:PC Client Software#Using the Swarm Client|Using the Swarm Client]]''' :'''4. What are the Keyboard Commands for flying the Crazyflie?''' ::You can find a full list of all the Key Commands in '''[[:Keyboard Commands]]''' ::(Alternatively: See '''Step 4''' of '''[[:PC Client Software#Using the Swarm Client|Using the Swarm Client]]''') :'''5. How do I plot the Log Files that the Crazyflie Swarm Creates?''' ::See the '''[[:Logging#MATLAB Parser|MATLAB Parser]]''' section for examples. :'''6. Can I change what files are compiled during <code>make</code>?''' ::Yep! You need to modify the makefile in the Client directory. You can follow the example shown '''[[:PC Client Software#Makefile|here]]''' or make your own if you know how (but then this question would be irrelevant to you...). ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 0a131580999a0d24fba0c422b4c9b66020eec7e7 Crazyflie Swarm 0 2 268 245 2016-08-03T17:56:58Z Jnoronha 3 /* Future Project Ideas */ bolded future project ideas wikitext text/x-wiki The Crazyflie Swarm is a Networked Control platform designed for students to learn more about control and for researchers that wish to apply their research in practice. Platform development was started during the Summer of 2015 and continues to this day. Here you will find descriptions on how the platform works, how you can use it, and how you can get involved in developing the platform further! == Frequently Asked Questions == For help with common problems and troubleshooting please see the [[FAQ]]. == Background == The Crazyflie Swarm platform is based off of the ''Crazyflie'' Nano-quadcopter produced and maintained by [https://www.bitcraze.io/ Bitcraze]. The ''Crazyflie'' is completely open-source so we are able to look at and modify any part of the code and customize it to our needs. === Major Platform Components: === [[Image: High_Level_Figure_(Single_Radio_Single_Crazyflie_NO_NUMBERS_CROPPED).jpg‎|thumb|right|A high level overview of the Crazyflie Platform]] *[[PC Client Software]] *[[Firmware]] *[[USB Radio]] == Modifying the Platform == [[Image:SingleRadioMultiCrazyflie.jpg|thumb|right|A high level overview of the Swarm Platform we created]] *[[Controller]] *[[Logging]] *[[Keyboard Commands]] *[[USB Radio#Changing Radio Channel|Changing Radio Channel]] *[[Flight Modes]] *[[Callbacks]] *[[Adding a Crazyflie]] *[[:Firmware]] ==Future Project Ideas== The whole concept of this Platform is to constantly expand its capabilities. If you are interested in developing this platform further here are some ideas to get you started! Additional details on any of these ideas can be found on the '''[[Future Project Ideas]]''' page. *[[:Future Project Ideas#Migrating Swarm Client PID's to Firmware|Migrating Swarm Client PID's to Firmware]] *[[:Future Project Ideas#Model Development/Verification and Tuning X, Y, and Z Location PID's|Model Development/Verification and Tuning X, Y, and Z Location PID's]] *[[:Future Project Ideas#Adding Parameter Support to Swarm Client|Adding Parameter Support to Swarm Client]] *[[:Future Project Ideas#Threading Each USB Radio to speed up Computation|Threading Each USB Radio to speed up Computation]] *[[:Future Project Ideas#Developing New Controllers for the Crazyflie (pending Model Development)|Developing New Controllers for the Crazyflie (pending Model Development)]] *[[:Future Project Ideas#Develop Communications Network Between Crazyflies|Develop Communications Network Between Crazyflies]] *[[:Future Project Ideas#Trilateration Position Estimation using a Swarm|Trilateration Position Estimation using a Swarm]] == [https://wiki.bitcraze.io/ Bitcraze Wiki] == Bitcraze maintains their own wiki on the many Crazyflie systems. If you can't find what you are looking for here, chances are they will have something to help. c59c02b73a7a5e9fd8ba633f60e99387f3f9a291 Future Project Ideas 0 47 269 176 2016-08-03T18:18:21Z Jnoronha 3 /* Developing New Controllers for the Crazyflie (pending Model Development) */ finished wikitext text/x-wiki Here we will go into more depth on what each of these projects would require: ==Migrating Swarm Client PID's to Firmware== ===Focus Area=== '''Firmware Programming and Communication Protocols''' *This project requires heavy modification of the Firmware and Communication systems inside the Crazyflie. ===Tasks=== ====Firmware==== *'''(HARD)''' Modifying [https://wiki.bitcraze.io/projects:crazyflie:crtp:commander Commander Packet Structure] to allow position data to be sent rather than pitch, roll, yaw, and thrust setpoints. *Modifying Firmware to pass the new position data into the correct place for use by the Firmware PID controllers. ====Client==== *Modify Swarm Client packet construction to match new commander packet protocol in Firmware *'''(EASY)''' Remove Controllers from callbacks and just send location packets to Crazyflies while still maintaining other functionality. ===Benefits=== *Significantly reduces Client-side computation and allows Crazyflie swarm to share the load. *'''Potential extension:''' Completely independent Crazyflie flight (i.e. No Client needed at all) ==Model Development/Verification and Tuning X, Y, and Z Location PID's== ===Focus Area=== '''Control Systems and Model Development/Verification''' *This project will require developing a model of the Crazyflie system and using the Model to calculate PID constants. ===Tasks=== *'''(HARD)''' Identify model Parameters for the Crazyflie *Construct model in Simulink and Verify simulation compared to test data *'''(EASY)''' Derive PID constants from verified model, test flight performance ===Benefits=== *'''VERIFIED MODEL!!''' We can do many things once we have a verified model of the system. *Flight performance will be greatly improved allowing more complex applications to be developed. *'''Potential extension:''' Path prediction algorithms and optimal pathing between points with obstacles ==Adding Parameter Support to Swarm Client== ===Focus Area=== '''Communications Protocols and Networking''' *This project will require Client-side software development to create helper functions for easy modification of parameters on the Crazyflie Firmware ===Tasks=== *Creating packet framework in the Client to replicate the [https://wiki.bitcraze.io/projects:crazyflie:firmware:comm_protocol#parameters parameters packet protocol] *Programming helper functions to make it simple to modify parameters **Ex. Write Parameter Value: <code>setParam(string "param_group.param_name", int set_value);</code> **Ex. Read Parameter Value: <code>readParam(string "param_group.param_name");</code> ===Benefits=== *Won't have to re-flash Firmware every time we want to test a parameter change (Improves Firmware testing efficiency) *Less Firmware modification if we can just write params during Client init. *'''Potential Extension:''' Tuning Firmware PID constants ==Threading Each USB Radio to speed up Computation== ===Focus Area=== '''Computer Architecture and Parallelization''' *This project will require/develop a good understanding of parallel processing and computer architecture. ===Tasks=== *Apply threading to each USB Radio individually **A single Radio will be assigned at most 3 Crazyflies, and each thread will handle the corresponding Callbacks for those Crazyflies (which includes control calculations, Radio communications, and logging for each Crazyflie) *Troubleshoot any issues that come up with non-sequential program execution (shouldn't have problems) ===Benefits=== *Greatly reduces time required to complete a loop cycle (relative to number of Crazyflies in the Swarm) **Improves scalability of the Swarm since we don't need to worry about missing the Camera System new data timing deadline as the Swarm size increases *'''Potential Extension:''' Increasing Swarm size to Camera System capacity limit. ==Developing New Controllers for the Crazyflie (pending Model Development)== ===Focus Area=== '''Control System Development and Implementation''' *This project will require a background in theoretical controls modeling and systems design. ===Tasks=== *Research Control Designs and decide which controller you want to use **Examples: State Feedback Control (LQR, LQI, Pole Placement), State Space Controller (Lyapunov Estimator, H2), etc.. *Develop a Simulink model for the controller and implement design in C++. *Verify model by comparing to real-world tests on the Crazyflie Swarm! ===Benefits=== *Improved flight control leading to more complex applications *Maintain control without all the information (State Estimation) *'''Potential Extension:''' Stable control with Stochastic lossy packet transmission ==Develop Communications Network Between Crazyflies== ==Trilateration Position Estimation using a Swarm== ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 35354c16a4b6ae4e3b2e27c39653ccfa10d1c715 272 269 2016-08-03T19:02:38Z Jnoronha 3 /* Develop Communications Network Between Crazyflies */ Finished section wikitext text/x-wiki Here we will go into more depth on what each of these projects would require: ==Migrating Swarm Client PID's to Firmware== ===Focus Area=== '''Firmware Programming and Communication Protocols''' *This project requires heavy modification of the Firmware and Communication systems inside the Crazyflie. ===Tasks=== ====Firmware==== *'''(HARD)''' Modifying [https://wiki.bitcraze.io/projects:crazyflie:crtp:commander Commander Packet Structure] to allow position data to be sent rather than pitch, roll, yaw, and thrust setpoints. *Modifying Firmware to pass the new position data into the correct place for use by the Firmware PID controllers. ====Client==== *Modify Swarm Client packet construction to match new commander packet protocol in Firmware *'''(EASY)''' Remove Controllers from callbacks and just send location packets to Crazyflies while still maintaining other functionality. ===Benefits=== *Significantly reduces Client-side computation and allows Crazyflie swarm to share the load. *'''Potential extension:''' Completely independent Crazyflie flight (i.e. No Client needed at all) ==Model Development/Verification and Tuning X, Y, and Z Location PID's== ===Focus Area=== '''Control Systems and Model Development/Verification''' *This project will require developing a model of the Crazyflie system and using the Model to calculate PID constants. ===Tasks=== *'''(HARD)''' Identify model Parameters for the Crazyflie *Construct model in Simulink and Verify simulation compared to test data *'''(EASY)''' Derive PID constants from verified model, test flight performance ===Benefits=== *'''VERIFIED MODEL!!''' We can do many things once we have a verified model of the system. *Flight performance will be greatly improved allowing more complex applications to be developed. *'''Potential extension:''' Path prediction algorithms and optimal pathing between points with obstacles ==Adding Parameter Support to Swarm Client== ===Focus Area=== '''Communications Protocols and Networking''' *This project will require Client-side software development to create helper functions for easy modification of parameters on the Crazyflie Firmware ===Tasks=== *Creating packet framework in the Client to replicate the [https://wiki.bitcraze.io/projects:crazyflie:firmware:comm_protocol#parameters parameters packet protocol] *Programming helper functions to make it simple to modify parameters **Ex. Write Parameter Value: <code>setParam(string "param_group.param_name", int set_value);</code> **Ex. Read Parameter Value: <code>readParam(string "param_group.param_name");</code> ===Benefits=== *Won't have to re-flash Firmware every time we want to test a parameter change (Improves Firmware testing efficiency) *Less Firmware modification if we can just write params during Client init. *'''Potential Extension:''' Tuning Firmware PID constants ==Threading Each USB Radio to speed up Computation== ===Focus Area=== '''Computer Architecture and Parallelization''' *This project will require/develop a good understanding of parallel processing and computer architecture. ===Tasks=== *Apply threading to each USB Radio individually **A single Radio will be assigned at most 3 Crazyflies, and each thread will handle the corresponding Callbacks for those Crazyflies (which includes control calculations, Radio communications, and logging for each Crazyflie) *Troubleshoot any issues that come up with non-sequential program execution (shouldn't have problems) ===Benefits=== *Greatly reduces time required to complete a loop cycle (relative to number of Crazyflies in the Swarm) **Improves scalability of the Swarm since we don't need to worry about missing the Camera System new data timing deadline as the Swarm size increases *'''Potential Extension:''' Increasing Swarm size to Camera System capacity limit. ==Developing New Controllers for the Crazyflie (pending Model Development)== ===Focus Area=== '''Control System Development and Implementation''' *This project will require a background in theoretical controls modeling and systems design. ===Tasks=== *Research Control Designs and decide which controller you want to use **Examples: State Feedback Control (LQR, LQI, Pole Placement), State Space Controller (Lyapunov Estimator, H2), etc.. *Develop a Simulink model for the controller and implement design in C++. *Verify model by comparing to real-world tests on the Crazyflie Swarm! ===Benefits=== *Improved flight control leading to more complex applications *Maintain control without all the information (State Estimation) *'''Potential Extension:''' Stable control with Stochastic lossy packet transmission ==Develop Communications Network Between Crazyflies== ===Focus Area=== '''Communication Networking and Firmware Development''' *This project will require/develop a good understanding of network protocols and creating complex communications networks ===Tasks=== *Research the Crazy RealTime Protocol (CRTP) used by the Crazyflie **[https://wiki.bitcraze.io/projects:crazyflie:firmware:comm_protocol CRTP Protocol] **[https://github.com/bitcraze/crazyflie2-nrf-firmware/blob/master/src/esb.c Enhanced Shock Burst USB Radio Protocol] *'''(HARD)''' Modify the Crazyflie Firmware to enable both transmit (tx) and receive (rx) packets *'''(HARD)''' Develop a system in Firmware to utilize the bi-directional communications **Example: Using the pitch, roll, or yaw of a Crazyflie to influence control of another Crazyflie(s) without passing it through the Swarm Client ===Benefits=== *Crazyflies can pass information between themselves *Stepping stone to fully autonomous Crazyflie Swamrs (No Client needed) *Opens up many possible extended applications *'''Potential Extensions:''' **Relative Swarm Formations (patterns based on distance from other members of the swarm, not some global entity) **Create Advanced [[#Trilateration Position Estimation using a Swarm|Trilateration Localization]] using Swarm itself ==Trilateration Position Estimation using a Swarm== ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 763afd32a286ce2dd344f4af35499fe26f7bd274 273 272 2016-08-03T19:31:52Z Jnoronha 3 /* Trilateration Position Estimation using a Swarm */ finished wikitext text/x-wiki Here we will go into more depth on what each of these projects would require: ==Migrating Swarm Client PID's to Firmware== ===Focus Area=== '''Firmware Programming and Communication Protocols''' *This project requires heavy modification of the Firmware and Communication systems inside the Crazyflie. ===Tasks=== ====Firmware==== *'''(HARD)''' Modifying [https://wiki.bitcraze.io/projects:crazyflie:crtp:commander Commander Packet Structure] to allow position data to be sent rather than pitch, roll, yaw, and thrust setpoints. *Modifying Firmware to pass the new position data into the correct place for use by the Firmware PID controllers. ====Client==== *Modify Swarm Client packet construction to match new commander packet protocol in Firmware *'''(EASY)''' Remove Controllers from callbacks and just send location packets to Crazyflies while still maintaining other functionality. ===Benefits=== *Significantly reduces Client-side computation and allows Crazyflie swarm to share the load. *'''Potential extension:''' Completely independent Crazyflie flight (i.e. No Client needed at all) ==Model Development/Verification and Tuning X, Y, and Z Location PID's== ===Focus Area=== '''Control Systems and Model Development/Verification''' *This project will require developing a model of the Crazyflie system and using the Model to calculate PID constants. ===Tasks=== *'''(HARD)''' Identify model Parameters for the Crazyflie *Construct model in Simulink and Verify simulation compared to test data *'''(EASY)''' Derive PID constants from verified model, test flight performance ===Benefits=== *'''VERIFIED MODEL!!''' We can do many things once we have a verified model of the system. *Flight performance will be greatly improved allowing more complex applications to be developed. *'''Potential extension:''' Path prediction algorithms and optimal pathing between points with obstacles ==Adding Parameter Support to Swarm Client== ===Focus Area=== '''Communications Protocols and Networking''' *This project will require Client-side software development to create helper functions for easy modification of parameters on the Crazyflie Firmware ===Tasks=== *Creating packet framework in the Client to replicate the [https://wiki.bitcraze.io/projects:crazyflie:firmware:comm_protocol#parameters parameters packet protocol] *Programming helper functions to make it simple to modify parameters **Ex. Write Parameter Value: <code>setParam(string "param_group.param_name", int set_value);</code> **Ex. Read Parameter Value: <code>readParam(string "param_group.param_name");</code> ===Benefits=== *Won't have to re-flash Firmware every time we want to test a parameter change (Improves Firmware testing efficiency) *Less Firmware modification if we can just write params during Client init. *'''Potential Extension:''' Tuning Firmware PID constants ==Threading Each USB Radio to speed up Computation== ===Focus Area=== '''Computer Architecture and Parallelization''' *This project will require/develop a good understanding of parallel processing and computer architecture. ===Tasks=== *Apply threading to each USB Radio individually **A single Radio will be assigned at most 3 Crazyflies, and each thread will handle the corresponding Callbacks for those Crazyflies (which includes control calculations, Radio communications, and logging for each Crazyflie) *Troubleshoot any issues that come up with non-sequential program execution (shouldn't have problems) ===Benefits=== *Greatly reduces time required to complete a loop cycle (relative to number of Crazyflies in the Swarm) **Improves scalability of the Swarm since we don't need to worry about missing the Camera System new data timing deadline as the Swarm size increases *'''Potential Extension:''' Increasing Swarm size to Camera System capacity limit. ==Developing New Controllers for the Crazyflie (pending Model Development)== ===Focus Area=== '''Control System Development and Implementation''' *This project will require a background in theoretical controls modeling and systems design. ===Tasks=== *Research Control Designs and decide which controller you want to use **Examples: State Feedback Control (LQR, LQI, Pole Placement), State Space Controller (Lyapunov Estimator, H2), etc.. *Develop a Simulink model for the controller and implement design in C++. *Verify model by comparing to real-world tests on the Crazyflie Swarm! ===Benefits=== *Improved flight control leading to more complex applications *Maintain control without all the information (State Estimation) *'''Potential Extension:''' Stable control with Stochastic lossy packet transmission ==Develop Communications Network Between Crazyflies== ===Focus Area=== '''Communication Networking and Firmware Development''' *This project will require/develop a good understanding of network protocols and creating complex communications networks ===Tasks=== *Research the Crazy RealTime Protocol (CRTP) used by the Crazyflie **[https://wiki.bitcraze.io/projects:crazyflie:firmware:comm_protocol CRTP Protocol] **[https://github.com/bitcraze/crazyflie2-nrf-firmware/blob/master/src/esb.c Enhanced Shock Burst USB Radio Protocol] *'''(HARD)''' Modify the Crazyflie Firmware to enable both transmit (tx) and receive (rx) packets *'''(HARD)''' Develop a system in Firmware to utilize the bi-directional communications **Example: Using the pitch, roll, or yaw of a Crazyflie to influence control of another Crazyflie(s) without passing it through the Swarm Client ===Benefits=== *Crazyflies can pass information between themselves *Stepping stone to fully autonomous Crazyflie Swamrs (No Client needed) *Opens up many possible extended applications *'''Potential Extensions:''' **Relative Swarm Formations (patterns based on distance from other members of the swarm, not some global entity) **Create Advanced [[#Trilateration Position Estimation using a Swarm|Trilateration Localization]] using Swarm itself ==Trilateration Position Estimation using a Swarm== ===Focus Area=== '''Stochastic Lossy Networks and Localization Methods''' *This project will develop a noise model for the Crazyflie communications in the lab and use that information to estimate an unknown Crazyflie's position. ===Tasks=== *Research Trilateration and Develop noise models for the Lab environment **[https://iastate.box.com/s/kfmvun479t83fyp5mjntokdyq5rtx802 Simple Proof of Concept example] **[https://iastate.box.com/s/34jf1ekow2wltun1qpsv3xighuaz4c0i Trilateration Matlab Code] *'''(HARD)''' Develop Client-side sub-routine to collect Received Signal Strength Indicator (RSSI) value from each node (Crazyflie or USB Radio) *'''(EASY)''' Develop Client-side sub-routine to calculate location estimate using RSSI based Trilateration method *Use position estimate to maintain stable flight without the use of the Camera System ===Benefits=== *Stepping stone to Outdoor Localization (effective outdoor localization method complimentary with GPS) *Reduces dependence on Camera System for localization *'''Potential Extension:''' Relative Swarm Formations (position dependent on distance from other members of the swarm, rather than a 'global' origin) ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> c661bea9009dbd06428e49f493100d66c9a7bc84 274 273 2016-08-03T19:33:01Z Jnoronha 3 added big quad deck project wikitext text/x-wiki Here we will go into more depth on what each of these projects would require: ==Migrating Swarm Client PID's to Firmware== ===Focus Area=== '''Firmware Programming and Communication Protocols''' *This project requires heavy modification of the Firmware and Communication systems inside the Crazyflie. ===Tasks=== ====Firmware==== *'''(HARD)''' Modifying [https://wiki.bitcraze.io/projects:crazyflie:crtp:commander Commander Packet Structure] to allow position data to be sent rather than pitch, roll, yaw, and thrust setpoints. *Modifying Firmware to pass the new position data into the correct place for use by the Firmware PID controllers. ====Client==== *Modify Swarm Client packet construction to match new commander packet protocol in Firmware *'''(EASY)''' Remove Controllers from callbacks and just send location packets to Crazyflies while still maintaining other functionality. ===Benefits=== *Significantly reduces Client-side computation and allows Crazyflie swarm to share the load. *'''Potential extension:''' Completely independent Crazyflie flight (i.e. No Client needed at all) ==Model Development/Verification and Tuning X, Y, and Z Location PID's== ===Focus Area=== '''Control Systems and Model Development/Verification''' *This project will require developing a model of the Crazyflie system and using the Model to calculate PID constants. ===Tasks=== *'''(HARD)''' Identify model Parameters for the Crazyflie *Construct model in Simulink and Verify simulation compared to test data *'''(EASY)''' Derive PID constants from verified model, test flight performance ===Benefits=== *'''VERIFIED MODEL!!''' We can do many things once we have a verified model of the system. *Flight performance will be greatly improved allowing more complex applications to be developed. *'''Potential extension:''' Path prediction algorithms and optimal pathing between points with obstacles ==Adding Parameter Support to Swarm Client== ===Focus Area=== '''Communications Protocols and Networking''' *This project will require Client-side software development to create helper functions for easy modification of parameters on the Crazyflie Firmware ===Tasks=== *Creating packet framework in the Client to replicate the [https://wiki.bitcraze.io/projects:crazyflie:firmware:comm_protocol#parameters parameters packet protocol] *Programming helper functions to make it simple to modify parameters **Ex. Write Parameter Value: <code>setParam(string "param_group.param_name", int set_value);</code> **Ex. Read Parameter Value: <code>readParam(string "param_group.param_name");</code> ===Benefits=== *Won't have to re-flash Firmware every time we want to test a parameter change (Improves Firmware testing efficiency) *Less Firmware modification if we can just write params during Client init. *'''Potential Extension:''' Tuning Firmware PID constants ==Threading Each USB Radio to speed up Computation== ===Focus Area=== '''Computer Architecture and Parallelization''' *This project will require/develop a good understanding of parallel processing and computer architecture. ===Tasks=== *Apply threading to each USB Radio individually **A single Radio will be assigned at most 3 Crazyflies, and each thread will handle the corresponding Callbacks for those Crazyflies (which includes control calculations, Radio communications, and logging for each Crazyflie) *Troubleshoot any issues that come up with non-sequential program execution (shouldn't have problems) ===Benefits=== *Greatly reduces time required to complete a loop cycle (relative to number of Crazyflies in the Swarm) **Improves scalability of the Swarm since we don't need to worry about missing the Camera System new data timing deadline as the Swarm size increases *'''Potential Extension:''' Increasing Swarm size to Camera System capacity limit. ==Developing New Controllers for the Crazyflie (pending Model Development)== ===Focus Area=== '''Control System Development and Implementation''' *This project will require a background in theoretical controls modeling and systems design. ===Tasks=== *Research Control Designs and decide which controller you want to use **Examples: State Feedback Control (LQR, LQI, Pole Placement), State Space Controller (Lyapunov Estimator, H2), etc.. *Develop a Simulink model for the controller and implement design in C++. *Verify model by comparing to real-world tests on the Crazyflie Swarm! ===Benefits=== *Improved flight control leading to more complex applications *Maintain control without all the information (State Estimation) *'''Potential Extension:''' Stable control with Stochastic lossy packet transmission ==Develop Communications Network Between Crazyflies== ===Focus Area=== '''Communication Networking and Firmware Development''' *This project will require/develop a good understanding of network protocols and creating complex communications networks ===Tasks=== *Research the Crazy RealTime Protocol (CRTP) used by the Crazyflie **[https://wiki.bitcraze.io/projects:crazyflie:firmware:comm_protocol CRTP Protocol] **[https://github.com/bitcraze/crazyflie2-nrf-firmware/blob/master/src/esb.c Enhanced Shock Burst USB Radio Protocol] *'''(HARD)''' Modify the Crazyflie Firmware to enable both transmit (tx) and receive (rx) packets *'''(HARD)''' Develop a system in Firmware to utilize the bi-directional communications **Example: Using the pitch, roll, or yaw of a Crazyflie to influence control of another Crazyflie(s) without passing it through the Swarm Client ===Benefits=== *Crazyflies can pass information between themselves *Stepping stone to fully autonomous Crazyflie Swamrs (No Client needed) *Opens up many possible extended applications *'''Potential Extensions:''' **Relative Swarm Formations (patterns based on distance from other members of the swarm, not some global entity) **Create Advanced [[#Trilateration Position Estimation using a Swarm|Trilateration Localization]] using Swarm itself ==Trilateration Position Estimation using a Swarm== ===Focus Area=== '''Stochastic Lossy Networks and Localization Methods''' *This project will develop a noise model for the Crazyflie communications in the lab and use that information to estimate an unknown Crazyflie's position. ===Tasks=== *Research Trilateration and Develop noise models for the Lab environment **[https://iastate.box.com/s/kfmvun479t83fyp5mjntokdyq5rtx802 Simple Proof of Concept example] **[https://iastate.box.com/s/34jf1ekow2wltun1qpsv3xighuaz4c0i Trilateration Matlab Code] *'''(HARD)''' Develop Client-side sub-routine to collect Received Signal Strength Indicator (RSSI) value from each node (Crazyflie or USB Radio) *'''(EASY)''' Develop Client-side sub-routine to calculate location estimate using RSSI based Trilateration method *Use position estimate to maintain stable flight without the use of the Camera System ===Benefits=== *Stepping stone to Outdoor Localization (effective outdoor localization method complimentary with GPS) *Reduces dependence on Camera System for localization *'''Potential Extension:''' Relative Swarm Formations (position dependent on distance from other members of the swarm, rather than a 'global' origin) ==Extending Swarm Client to Larger Quadcopters== ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 4e6084385d07b6bda89d7b469c81bedcc3a13ce9 275 274 2016-08-03T19:47:58Z Jnoronha 3 finished BigQuad Deck section wikitext text/x-wiki Here we will go into more depth on what each of these projects would require: ==Migrating Swarm Client PID's to Firmware== ===Focus Area=== '''Firmware Programming and Communication Protocols''' *This project requires heavy modification of the Firmware and Communication systems inside the Crazyflie. ===Tasks=== ====Firmware==== *'''(HARD)''' Modifying [https://wiki.bitcraze.io/projects:crazyflie:crtp:commander Commander Packet Structure] to allow position data to be sent rather than pitch, roll, yaw, and thrust setpoints. *Modifying Firmware to pass the new position data into the correct place for use by the Firmware PID controllers. ====Client==== *Modify Swarm Client packet construction to match new commander packet protocol in Firmware *'''(EASY)''' Remove Controllers from callbacks and just send location packets to Crazyflies while still maintaining other functionality. ===Benefits=== *Significantly reduces Client-side computation and allows Crazyflie swarm to share the load. *'''Potential extension:''' Completely independent Crazyflie flight (i.e. No Client needed at all) ==Model Development/Verification and Tuning X, Y, and Z Location PID's== ===Focus Area=== '''Control Systems and Model Development/Verification''' *This project will require developing a model of the Crazyflie system and using the Model to calculate PID constants. ===Tasks=== *'''(HARD)''' Identify model Parameters for the Crazyflie *Construct model in Simulink and Verify simulation compared to test data *'''(EASY)''' Derive PID constants from verified model, test flight performance ===Benefits=== *'''VERIFIED MODEL!!''' We can do many things once we have a verified model of the system. *Flight performance will be greatly improved allowing more complex applications to be developed. *'''Potential extension:''' Path prediction algorithms and optimal pathing between points with obstacles ==Adding Parameter Support to Swarm Client== ===Focus Area=== '''Communications Protocols and Networking''' *This project will require Client-side software development to create helper functions for easy modification of parameters on the Crazyflie Firmware ===Tasks=== *Creating packet framework in the Client to replicate the [https://wiki.bitcraze.io/projects:crazyflie:firmware:comm_protocol#parameters parameters packet protocol] *Programming helper functions to make it simple to modify parameters **Ex. Write Parameter Value: <code>setParam(string "param_group.param_name", int set_value);</code> **Ex. Read Parameter Value: <code>readParam(string "param_group.param_name");</code> ===Benefits=== *Won't have to re-flash Firmware every time we want to test a parameter change (Improves Firmware testing efficiency) *Less Firmware modification if we can just write params during Client init. *'''Potential Extension:''' Tuning Firmware PID constants ==Threading Each USB Radio to speed up Computation== ===Focus Area=== '''Computer Architecture and Parallelization''' *This project will require/develop a good understanding of parallel processing and computer architecture. ===Tasks=== *Apply threading to each USB Radio individually **A single Radio will be assigned at most 3 Crazyflies, and each thread will handle the corresponding Callbacks for those Crazyflies (which includes control calculations, Radio communications, and logging for each Crazyflie) *Troubleshoot any issues that come up with non-sequential program execution (shouldn't have problems) ===Benefits=== *Greatly reduces time required to complete a loop cycle (relative to number of Crazyflies in the Swarm) **Improves scalability of the Swarm since we don't need to worry about missing the Camera System new data timing deadline as the Swarm size increases *'''Potential Extension:''' Increasing Swarm size to Camera System capacity limit. ==Developing New Controllers for the Crazyflie (pending Model Development)== ===Focus Area=== '''Control System Development and Implementation''' *This project will require a background in theoretical controls modeling and systems design. ===Tasks=== *Research Control Designs and decide which controller you want to use **Examples: State Feedback Control (LQR, LQI, Pole Placement), State Space Controller (Lyapunov Estimator, H2), etc.. *Develop a Simulink model for the controller and implement design in C++. *Verify model by comparing to real-world tests on the Crazyflie Swarm! ===Benefits=== *Improved flight control leading to more complex applications *Maintain control without all the information (State Estimation) *'''Potential Extension:''' Stable control with Stochastic lossy packet transmission ==Develop Communications Network Between Crazyflies== ===Focus Area=== '''Communication Networking and Firmware Development''' *This project will require/develop a good understanding of network protocols and creating complex communications networks ===Tasks=== *Research the Crazy RealTime Protocol (CRTP) used by the Crazyflie **[https://wiki.bitcraze.io/projects:crazyflie:firmware:comm_protocol CRTP Protocol] **[https://github.com/bitcraze/crazyflie2-nrf-firmware/blob/master/src/esb.c Enhanced Shock Burst USB Radio Protocol] *'''(HARD)''' Modify the Crazyflie Firmware to enable both transmit (tx) and receive (rx) packets *'''(HARD)''' Develop a system in Firmware to utilize the bi-directional communications **Example: Using the pitch, roll, or yaw of a Crazyflie to influence control of another Crazyflie(s) without passing it through the Swarm Client ===Benefits=== *Crazyflies can pass information between themselves *Stepping stone to fully autonomous Crazyflie Swamrs (No Client needed) *Opens up many possible extended applications *'''Potential Extensions:''' **Relative Swarm Formations (patterns based on distance from other members of the swarm, not some global entity) **Create Advanced [[#Trilateration Position Estimation using a Swarm|Trilateration Localization]] using Swarm itself ==Trilateration Position Estimation using a Swarm== ===Focus Area=== '''Stochastic Lossy Networks and Localization Methods''' *This project will develop a noise model for the Crazyflie communications in the lab and use that information to estimate an unknown Crazyflie's position. ===Tasks=== *Research Trilateration and Develop noise models for the Lab environment **[https://iastate.box.com/s/kfmvun479t83fyp5mjntokdyq5rtx802 Simple Proof of Concept example] **[https://iastate.box.com/s/34jf1ekow2wltun1qpsv3xighuaz4c0i Trilateration Matlab Code] *'''(HARD)''' Develop Client-side sub-routine to collect Received Signal Strength Indicator (RSSI) value from each node (Crazyflie or USB Radio) *'''(EASY)''' Develop Client-side sub-routine to calculate location estimate using RSSI based Trilateration method *Use position estimate to maintain stable flight without the use of the Camera System ===Benefits=== *Stepping stone to Outdoor Localization (effective outdoor localization method complimentary with GPS) *Reduces dependence on Camera System for localization *'''Potential Extension:''' Relative Swarm Formations (position dependent on distance from other members of the swarm, rather than a 'global' origin) ==Extending Swarm Client to Larger Quadcopters== ===Focus Area=== '''Hardware Development and System Modeling''' *This project will utilize the [https://www.bitcraze.io/bigquad-deck/ Crazyflie's BigQuad Deck] Expansion board to convert the motor commands to signals for ESC motor controllers ===Tasks=== *Research the BigQuad Deck and the Crazyflie Client functionality *Derive System Model and parameters for the large Quadcopter *Develop a simple test bench for testing the motor command conversion safely *Run Flight tests to validate the system model and stability of the scaled-up quadcopter ===Benefits=== *Allows other lab projects to utilize the Crazyflie's onboard 10-DOF (acc, gyro, mag, baro) sensors without the size, battery, and payload limitations of the Crazyflie! *Use the Swarm Client Platform as a 'universal' backbone for lab projects. *'''Potential Extension:''' Mount the Crazyflie onto ANY Quadcopter based application and program the Swarm Client to run the application. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 694841270203a916c55b7e47d5a3c2f1c02b25e2 276 275 2016-08-03T19:48:16Z Jnoronha 3 fixed spacing of directory wikitext text/x-wiki Here we will go into more depth on what each of these projects would require: ==Migrating Swarm Client PID's to Firmware== ===Focus Area=== '''Firmware Programming and Communication Protocols''' *This project requires heavy modification of the Firmware and Communication systems inside the Crazyflie. ===Tasks=== ====Firmware==== *'''(HARD)''' Modifying [https://wiki.bitcraze.io/projects:crazyflie:crtp:commander Commander Packet Structure] to allow position data to be sent rather than pitch, roll, yaw, and thrust setpoints. *Modifying Firmware to pass the new position data into the correct place for use by the Firmware PID controllers. ====Client==== *Modify Swarm Client packet construction to match new commander packet protocol in Firmware *'''(EASY)''' Remove Controllers from callbacks and just send location packets to Crazyflies while still maintaining other functionality. ===Benefits=== *Significantly reduces Client-side computation and allows Crazyflie swarm to share the load. *'''Potential extension:''' Completely independent Crazyflie flight (i.e. No Client needed at all) ==Model Development/Verification and Tuning X, Y, and Z Location PID's== ===Focus Area=== '''Control Systems and Model Development/Verification''' *This project will require developing a model of the Crazyflie system and using the Model to calculate PID constants. ===Tasks=== *'''(HARD)''' Identify model Parameters for the Crazyflie *Construct model in Simulink and Verify simulation compared to test data *'''(EASY)''' Derive PID constants from verified model, test flight performance ===Benefits=== *'''VERIFIED MODEL!!''' We can do many things once we have a verified model of the system. *Flight performance will be greatly improved allowing more complex applications to be developed. *'''Potential extension:''' Path prediction algorithms and optimal pathing between points with obstacles ==Adding Parameter Support to Swarm Client== ===Focus Area=== '''Communications Protocols and Networking''' *This project will require Client-side software development to create helper functions for easy modification of parameters on the Crazyflie Firmware ===Tasks=== *Creating packet framework in the Client to replicate the [https://wiki.bitcraze.io/projects:crazyflie:firmware:comm_protocol#parameters parameters packet protocol] *Programming helper functions to make it simple to modify parameters **Ex. Write Parameter Value: <code>setParam(string "param_group.param_name", int set_value);</code> **Ex. Read Parameter Value: <code>readParam(string "param_group.param_name");</code> ===Benefits=== *Won't have to re-flash Firmware every time we want to test a parameter change (Improves Firmware testing efficiency) *Less Firmware modification if we can just write params during Client init. *'''Potential Extension:''' Tuning Firmware PID constants ==Threading Each USB Radio to speed up Computation== ===Focus Area=== '''Computer Architecture and Parallelization''' *This project will require/develop a good understanding of parallel processing and computer architecture. ===Tasks=== *Apply threading to each USB Radio individually **A single Radio will be assigned at most 3 Crazyflies, and each thread will handle the corresponding Callbacks for those Crazyflies (which includes control calculations, Radio communications, and logging for each Crazyflie) *Troubleshoot any issues that come up with non-sequential program execution (shouldn't have problems) ===Benefits=== *Greatly reduces time required to complete a loop cycle (relative to number of Crazyflies in the Swarm) **Improves scalability of the Swarm since we don't need to worry about missing the Camera System new data timing deadline as the Swarm size increases *'''Potential Extension:''' Increasing Swarm size to Camera System capacity limit. ==Developing New Controllers for the Crazyflie (pending Model Development)== ===Focus Area=== '''Control System Development and Implementation''' *This project will require a background in theoretical controls modeling and systems design. ===Tasks=== *Research Control Designs and decide which controller you want to use **Examples: State Feedback Control (LQR, LQI, Pole Placement), State Space Controller (Lyapunov Estimator, H2), etc.. *Develop a Simulink model for the controller and implement design in C++. *Verify model by comparing to real-world tests on the Crazyflie Swarm! ===Benefits=== *Improved flight control leading to more complex applications *Maintain control without all the information (State Estimation) *'''Potential Extension:''' Stable control with Stochastic lossy packet transmission ==Develop Communications Network Between Crazyflies== ===Focus Area=== '''Communication Networking and Firmware Development''' *This project will require/develop a good understanding of network protocols and creating complex communications networks ===Tasks=== *Research the Crazy RealTime Protocol (CRTP) used by the Crazyflie **[https://wiki.bitcraze.io/projects:crazyflie:firmware:comm_protocol CRTP Protocol] **[https://github.com/bitcraze/crazyflie2-nrf-firmware/blob/master/src/esb.c Enhanced Shock Burst USB Radio Protocol] *'''(HARD)''' Modify the Crazyflie Firmware to enable both transmit (tx) and receive (rx) packets *'''(HARD)''' Develop a system in Firmware to utilize the bi-directional communications **Example: Using the pitch, roll, or yaw of a Crazyflie to influence control of another Crazyflie(s) without passing it through the Swarm Client ===Benefits=== *Crazyflies can pass information between themselves *Stepping stone to fully autonomous Crazyflie Swamrs (No Client needed) *Opens up many possible extended applications *'''Potential Extensions:''' **Relative Swarm Formations (patterns based on distance from other members of the swarm, not some global entity) **Create Advanced [[#Trilateration Position Estimation using a Swarm|Trilateration Localization]] using Swarm itself ==Trilateration Position Estimation using a Swarm== ===Focus Area=== '''Stochastic Lossy Networks and Localization Methods''' *This project will develop a noise model for the Crazyflie communications in the lab and use that information to estimate an unknown Crazyflie's position. ===Tasks=== *Research Trilateration and Develop noise models for the Lab environment **[https://iastate.box.com/s/kfmvun479t83fyp5mjntokdyq5rtx802 Simple Proof of Concept example] **[https://iastate.box.com/s/34jf1ekow2wltun1qpsv3xighuaz4c0i Trilateration Matlab Code] *'''(HARD)''' Develop Client-side sub-routine to collect Received Signal Strength Indicator (RSSI) value from each node (Crazyflie or USB Radio) *'''(EASY)''' Develop Client-side sub-routine to calculate location estimate using RSSI based Trilateration method *Use position estimate to maintain stable flight without the use of the Camera System ===Benefits=== *Stepping stone to Outdoor Localization (effective outdoor localization method complimentary with GPS) *Reduces dependence on Camera System for localization *'''Potential Extension:''' Relative Swarm Formations (position dependent on distance from other members of the swarm, rather than a 'global' origin) ==Extending Swarm Client to Larger Quadcopters== ===Focus Area=== '''Hardware Development and System Modeling''' *This project will utilize the [https://www.bitcraze.io/bigquad-deck/ Crazyflie's BigQuad Deck] Expansion board to convert the motor commands to signals for ESC motor controllers ===Tasks=== *Research the BigQuad Deck and the Crazyflie Client functionality *Derive System Model and parameters for the large Quadcopter *Develop a simple test bench for testing the motor command conversion safely *Run Flight tests to validate the system model and stability of the scaled-up quadcopter ===Benefits=== *Allows other lab projects to utilize the Crazyflie's onboard 10-DOF (acc, gyro, mag, baro) sensors without the size, battery, and payload limitations of the Crazyflie! *Use the Swarm Client Platform as a 'universal' backbone for lab projects. *'''Potential Extension:''' Mount the Crazyflie onto ANY Quadcopter based application and program the Swarm Client to run the application. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 48f7221222d9292c4cf370f14d2093dffb5e67a4 File:CrazyflieFirmwareArchitecture.png 6 80 270 2016-08-03T18:45:06Z Jnoronha 3 Block diagram of the Crazyflie Firmware system wikitext text/x-wiki Block diagram of the Crazyflie Firmware system 1436e30dbf2b6e69a5a543da6b8ea008c52c51d6 297 270 2016-08-27T17:44:32Z Jnoronha 3 Jnoronha uploaded a new version of [[File:CrazyflieFirmwareArchitecture.png]] wikitext text/x-wiki Block diagram of the Crazyflie Firmware system 1436e30dbf2b6e69a5a543da6b8ea008c52c51d6 Firmware 0 26 271 248 2016-08-03T18:48:26Z Jnoronha 3 added firmware architecture and separated sections wikitext text/x-wiki The Firmware architecture layout: [[Image:CrazyflieFirmwareArchitecture.png|700px]] [https://www.bitcraze.io/2015/01/crazyflie-2-0-radio-communication/ Crazyflie Firmware Architecture Layout] ==Firmware Modifications== Not much work has been done in the Firmware yet (as of 7/20/16). The few things we have been able to successfully modify are: #Creating New Log Blocks #Modifying the Default Yaw Mode #Adding and Modifying Parameter Values ==New Firmware Log Blocks== In the Crazyflie Firmware there is a generalized logging framework that allows us to make any group of variables into a log block. It makes things very easy to log. Here are a few examples: :'''IMPORTANT:''' If you want to create new Log groups in a file, make sure you include <code>#include "log.h"</code> at the top of the file. :Ex. 1. Magnometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(mag) LOG_ADD(LOG_FLOAT, x, &mag.x) LOG_ADD(LOG_FLOAT, y, &mag.y) LOG_ADD(LOG_FLOAT, z, &mag.z) LOG_GROUP_STOP(mag) </pre> </code> </blockquote> ::So with this code we have created a log block called 'mag' and it contains the X, Y, and Z measurements from the magnetometer sensor. :Ex. 2. Accelerometer Log Block (code found in ''Firmware > modules > src > stabilizer.c'') <blockquote> <code> <pre> LOG_GROUP_START(acc) LOG_ADD(LOG_FLOAT, x, &acc.x) LOG_ADD(LOG_FLOAT, y, &acc.y) LOG_ADD(LOG_FLOAT, z, &acc.z) LOG_ADD(LOG_FLOAT, zw, &accWZ) LOG_ADD(LOG_FLOAT, mag2, &accMAG) LOG_GROUP_STOP(acc) </pre> </code> </blockquote> ::Just like in the magnetometer block, here we have created a log group called 'acc' and inside this group we are logging the variables for the accelerometer's X, Y, and Z values as well as 2 other gravity based variables used for thrust compensation. ===Using New Log Blocks in Swarm Client=== Now that we have these new log blocks in the Firmware, we can [[:Logging#New Client Log Blocks|use log blocks in the Client]] ==Modify the Default Yaw Mode== There are 3 types of Yaw Modes available in the Firmware (as of 7/21/16), as shown (code in ''Firmware > modules > interface > commander.h'') <blockquote> <code> <pre> typedef enum { CAREFREE = 0, // Yaw is locked to world coordinates thus heading stays the same when yaw rotates PLUSMODE = 1, // Plus-mode. Motor M1 is defined as front XMODE = 2, // X-mode. M1 & M4 is defined as front } YawModeType; </pre> </code> </blockquote> :'''Note:''' The default mode for the Crazyflie 2.0 is ''XMODE''. The ''PLUSMODE'' is default for the Crazyflie 1.0, but can still be used on the Crazyflie 2.0 if desired. ===Carefree Mode=== ''CAREFREE'' mode is what our Crazyflie 2.0's are using, this mode applies a transformation to the Pitch and Roll setpoints depending on the angle of Yaw. We used to perform this calculation on the Client like this (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> #if USE_PR_YAW_CORRECT //CORRECTS PITCH AND ROLL PID ERRORS TO ACCOUNT FOR QUADS CURRENT YAW DIRECTION (_/57.2958 converts DEG to RADIANS) xError2 = cos(correctedYaw2 / 57.2958)*(xPositionDesired2 - xPosition2) - sin(correctedYaw2 / 57.2958)*(yPositionDesired2 - yPosition2); yError2 = sin(correctedYaw2 / 57.2958)*(xPositionDesired2 - xPosition2) + cos(correctedYaw2 / 57.2958)*(yPositionDesired2 - yPosition2); #else xError2 = xPositionDesired2 - xPosition2; yError2 = yPositionDesired2 - yPosition2; #endif controllerSetXYError(&pidCtrl2, xError2, yError2); </pre> </code> </blockquote> This is no longer necessary on the Client because this is the exact same calculation ''CAREFREE'' mode performs on the Firmware. So this reduces the computation done on the Client in each Crazyflie Callback. ====Changing Yaw Mode in Firmware==== To change the Yaw Mode to ''CAREFREE'' mode we had to make the modification shown (code in ''Firmware > modules > interface > commander.h (line 36)''): :'''ORIGINAL:''' <blockquote> <code> <pre> ... #ifdef PLATFORM_CF1 #define DEFUALT_YAW_MODE PLUSMODE #else #define DEFUALT_YAW_MODE XMODE #endif ... </pre> </code> </blockquote> :'''MODIFIED:''' <blockquote> <code> <pre> ... #ifdef PLATFORM_CF1 #define DEFUALT_YAW_MODE PLUSMODE #else #define DEFUALT_YAW_MODE CAREFREE #endif ... </pre> </code> </blockquote> ::The code checks for which version Crazyflie you are using, either the original Crazyflie (<code>PLATFORM_CF1</code>), or the Crazyflie 2.0. We are using the Crazyflie 2.0 so we only care about the 2nd ''DEFAULT_YAW_MODE'', which we modified to ''CAREFREE'' mode as shown. ==New Firmware Parameter Groups== Parameter groups are very similar to Log groups with a few key differences. An example of a Parameter group is shown (code in ''Firmware > modules > src > commander.c''): :'''IMPORTANT:''' If you want to create new Parameter groups in a file, make sure you include <code>#include "param.h"</code> at the top of the file. <blockquote> <code> <pre> // Params for flight modes PARAM_GROUP_START(flightmode) PARAM_ADD(PARAM_UINT8, althold, &altHoldMode) PARAM_ADD(PARAM_UINT8, yawMode, &yawMode) PARAM_ADD(PARAM_UINT8, yawRst, &carefreeResetFront) PARAM_ADD(PARAM_UINT8, stabModeRoll, &stabilizationModeRoll) PARAM_ADD(PARAM_UINT8, stabModePitch, &stabilizationModePitch) PARAM_ADD(PARAM_UINT8, stabModeYaw, &stabilizationModeYaw) PARAM_GROUP_STOP(flightmode) </pre> </code> </blockquote> :So we create a parameter group called ''flightmode'' that contains the parameters listed. The difference between Log variables and Param variables is that for Param variables you need to specify the variable type (''PARAM_UINT8'' shown in the example). Some User Friendly Param Types are shown below (you can find more complex Param types in ''Firmware > modules > interface > param.h''). <blockquote> <code> <pre> // User-friendly macros #define PARAM_UINT8 (PARAM_1BYTE | PARAM_TYPE_INT | PARAM_UNSIGNED) #define PARAM_INT8 (PARAM_1BYTE | PARAM_TYPE_INT | PARAM_SIGNED) #define PARAM_UINT16 (PARAM_2BYTES | PARAM_TYPE_INT | PARAM_UNSIGNED) #define PARAM_INT16 (PARAM_2BYTES | PARAM_TYPE_INT | PARAM_SIGNED) #define PARAM_UINT32 (PARAM_4BYTES | PARAM_TYPE_INT | PARAM_UNSIGNED) #define PARAM_INT32 (PARAM_4BYTES | PARAM_TYPE_INT | PARAM_SIGNED) </pre> </code> </blockquote> ===Using Param Groups in Client=== This is not implemented yet (as of 7/21/16) but would be very nice to have. We could then tune Firmware PID constants without needing to flash the Firmware each time and much more. If someone would like to [[:Future Project Ideas#Adding Parameter Support to Swarm Client|attempt to create this]] you can see the Bitcraze Wiki page on the [https://wiki.bitcraze.io/doc:crazyflie:crtp:param Params Protocol] for help on how to implement this. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> 23d1ea28d6da0d947fb24451a0af41c7d44e143a Setting up and Modifying RADA Simulations 0 81 277 2016-08-03T19:55:06Z Pfuhing 5 New page: == Simulink Setup == === Setting up the MATLAB Workspace === === Settings in Simulink === === Store Data from Simulink === == Understanding and Modifying RADA Simulations == === Compo... wikitext text/x-wiki == Simulink Setup == === Setting up the MATLAB Workspace === === Settings in Simulink === === Store Data from Simulink === == Understanding and Modifying RADA Simulations == === Components of the Model === ==== Body dynamics calculations ==== ==== Actuator dynamics calculations ==== ==== System commands ==== ==== Body velocity calculations ==== === Modifying Simulink === ==== Creating a new simulation ==== ==== Modifying existing files ==== 89afcaa7a4a1db7b4509badb5d124a9e4e2062f2 284 277 2016-08-04T19:56:41Z Pfuhing 5 wikitext text/x-wiki == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] === Setting up the MATLAB Workspace === === Settings in Simulink === === Store Data from Simulink === == Understanding and Modifying RADA Simulations == === Components of the Model === ==== Body dynamics calculations ==== ==== Actuator dynamics calculations ==== ==== System commands ==== ==== Body velocity calculations ==== === Modifying Simulink === ==== Creating a new simulation ==== ==== Modifying existing files ==== 4f6e65f323061f72bef0e73f8cfa33058d40d9b2 285 284 2016-08-04T20:26:56Z Pfuhing 5 wikitext text/x-wiki == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] Simulink comes with MATLAB. You should get MATLAB 2014b or latter to ensure the Simulink files from Paul Uhing's research repository will work with your installation of MATLAB. Once the install is complete and MATLAB is registered you can open MATLAB up. Then change the folder MATLAB will work out of to a directory you will want to work form. It would be best to copy a few files from Paul Uhing's repository to help you get started. Inside of the RADA Research Repository go to ''MATLAB/RADA'' and copy ''modelParams_smallWheels_RADA.m'', ''Hbrigeest.mat'', ''Kvw_calc.mat'', ''Hmu_r_erisLargeWheels.mat'', ''LQI_recalc.m'', and ''RADA_ctrlSep.m'' from this directory to you new diectroy as these files will allow you to load the model parameters and controller designs used in Paul Uhing's thesis or find the most recent version of these files an copy them instead. It would also be good to copy and of the ''RADA_psiCtrl_v2.slx'' or ''RADA_psiCtrl_LQGsep.slx'' files here to sever as the base RADA simulation in your new directory. Finally, open te ''DataSets'' directory below the ''RADA'' directory can copy one of the ''RADA_LQG_compPID.mat'' files or ''RADA_LQG_sep.mat'' files because it will allow you to have input vector for the copied ''.slx'' Simulink file. === Setting up the MATLAB Workspace === Now in MATLAB with you working directory set to you new directory for test RADA simulations run ''modelParams_smallWheels_RADA.m'' from the MATLAB command line ten load the RADA ''.mat'' data file. Now in the Current Folder screen in MATLAB double click on the ''.slx'' and wait for it to open. === Settings in Simulink === When running a simulation RADA in simulink always make sure your solver is set to '''ode23t'''! The RADA model is a moderately stiff set of differential equations and ode45 the default solver will take an extremely long time to run simulaitons of RADA. You can set the run length to any length you want and then run the simulation. === Store Data from Simulink === All of the Simulink files in Paul Uhing's Research Repository output simulation data MATLAB structures contain the time and value arrays for important variables. After a simulation finishes these will show up as variables in the MATLAB Workspace. If you want to save any of these values for latter use select them in the MATLAB Workspace and right-click and select save or press ctrl+s to save these varable to a ''.mat'' file. == Understanding and Modifying RADA Simulations == === Components of the Model === ==== Body dynamics calculations ==== ==== Actuator dynamics calculations ==== ==== System commands ==== ==== Body velocity calculations ==== === Modifying Simulink === ==== Creating a new simulation ==== ==== Modifying existing files ==== 518fa09ad10aad8cabc5095e70150e812aa257fb 286 285 2016-08-08T16:42:51Z Pfuhing 5 wikitext text/x-wiki == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] Simulink comes with MATLAB. You should get MATLAB 2014b or latter to ensure the Simulink files from Paul Uhing's research repository will work with your installation of MATLAB. Once the install is complete and MATLAB is registered you can open MATLAB up. Then change the folder MATLAB will work out of to a directory you will want to work form. It would be best to copy a few files from Paul Uhing's repository to help you get started. Inside of the RADA Research Repository go to ''MATLAB/RADA'' and copy ''modelParams_smallWheels_RADA.m'', ''Hbrigeest.mat'', ''Kvw_calc.mat'', ''Hmu_r_erisLargeWheels.mat'', ''LQI_recalc.m'', and ''RADA_ctrlSep.m'' from this directory to you new diectroy as these files will allow you to load the model parameters and controller designs used in Paul Uhing's thesis or find the most recent version of these files an copy them instead. It would also be good to copy and of the ''RADA_psiCtrl_v2.slx'' or ''RADA_psiCtrl_LQGsep.slx'' files here to sever as the base RADA simulation in your new directory. Finally, open te ''DataSets'' directory below the ''RADA'' directory can copy one of the ''RADA_LQG_compPID.mat'' files or ''RADA_LQG_sep.mat'' files because it will allow you to have input vector for the copied ''.slx'' Simulink file. === Setting up the MATLAB Workspace === Now in MATLAB with you working directory set to you new directory for test RADA simulations run ''modelParams_smallWheels_RADA.m'' from the MATLAB command line ten load the RADA ''.mat'' data file. Now in the Current Folder screen in MATLAB double click on the ''.slx'' and wait for it to open. === Settings in Simulink === When running a simulation RADA in simulink always make sure your solver is set to '''ode23t'''! The RADA model is a moderately stiff set of differential equations and ode45 the default solver will take an extremely long time to run simulaitons of RADA. You can set the run length to any length you want and then run the simulation. === Store Data from Simulink === All of the Simulink files in Paul Uhing's Research Repository output simulation data MATLAB structures contain the time and value arrays for important variables. After a simulation finishes these will show up as variables in the MATLAB Workspace. If you want to save any of these values for latter use select them in the MATLAB Workspace and right-click and select save or press ctrl+s to save these variables to a ''.mat'' file. == Understanding and Modifying RADA Simulations == The Simulink models of RADA for Paul Uhing's Thesis is built to be fairly easy to understand. Normal Simulink blocks are used for routing signals and completing simple calculations. For more difficult calculations MATLAB Function blocks are used. These blocks allow you to write MATLAB code to complete some calculation. They can have inputs from the Simulink simulation and parameter inputs from the MATLAB Workspace. This makes complex calculations much easier to understand. The goal of using all of these tricks is to avoid creating a model that is a rat's nest of interconnecting blocks that is impossible trace any errors in the simulation. Understanding how the RADA model was put together wil help you understand how to modify this model and how to build your own models. === Components of the Model === The model is broken down into subsystems based off of sub-components of the actual system. There is a block for calculating the accelerations of RADA's body, two blocks for calculating the different actuator sets, producing commands to the system, and calculating intermediate values used by other blocks. ==== Body dynamics calculations ==== The body dynamics block (''RADA_BodyDynamcis_v2'') takes in Euler angle position and velocity of the pendulum (including yaw), the global velocity of the ground vehicle, the force produced by the propellers in the x body direction of the pendulum, the force produced by the propellers in the y body direction of the pendulum, and the force produced by each wheel. This block is a MATLAB Function block so it also has parameter inputs. For using MATLAB Function block is is important to never delete: %#codegen because this allows the MATLAB code to function in Simulink. The code inside the block is just the implementation of the final equation in Chapter 3.4 of Paul Uhing's Thesis. The outputs of the block are the acceleration of the pendulum's in pitch and roll, the acceleration of the yaw of the system, and the x and y global acceleration of the ground robot. Then MATLAB continuous time integrator blocks are used to get the corresponding velocities and positions. MATLAB function blocks do not do integration very well so it is easier just to calculate the accelerations and then use the Simulink blocks to integrate. ==== Actuator dynamics calculations ==== ==== System commands ==== ==== Body velocity calculations ==== === Modifying Simulink === ==== Creating a new simulation ==== ==== Modifying existing files ==== 64bb9f1a930a672550f5c37e48ada168da6b2cc6 287 286 2016-08-08T17:29:31Z Pfuhing 5 /* Actuator dynamics calculations */ wikitext text/x-wiki == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] Simulink comes with MATLAB. You should get MATLAB 2014b or latter to ensure the Simulink files from Paul Uhing's research repository will work with your installation of MATLAB. Once the install is complete and MATLAB is registered you can open MATLAB up. Then change the folder MATLAB will work out of to a directory you will want to work form. It would be best to copy a few files from Paul Uhing's repository to help you get started. Inside of the RADA Research Repository go to ''MATLAB/RADA'' and copy ''modelParams_smallWheels_RADA.m'', ''Hbrigeest.mat'', ''Kvw_calc.mat'', ''Hmu_r_erisLargeWheels.mat'', ''LQI_recalc.m'', and ''RADA_ctrlSep.m'' from this directory to you new diectroy as these files will allow you to load the model parameters and controller designs used in Paul Uhing's thesis or find the most recent version of these files an copy them instead. It would also be good to copy and of the ''RADA_psiCtrl_v2.slx'' or ''RADA_psiCtrl_LQGsep.slx'' files here to sever as the base RADA simulation in your new directory. Finally, open te ''DataSets'' directory below the ''RADA'' directory can copy one of the ''RADA_LQG_compPID.mat'' files or ''RADA_LQG_sep.mat'' files because it will allow you to have input vector for the copied ''.slx'' Simulink file. === Setting up the MATLAB Workspace === Now in MATLAB with you working directory set to you new directory for test RADA simulations run ''modelParams_smallWheels_RADA.m'' from the MATLAB command line ten load the RADA ''.mat'' data file. Now in the Current Folder screen in MATLAB double click on the ''.slx'' and wait for it to open. === Settings in Simulink === When running a simulation RADA in simulink always make sure your solver is set to '''ode23t'''! The RADA model is a moderately stiff set of differential equations and ode45 the default solver will take an extremely long time to run simulaitons of RADA. You can set the run length to any length you want and then run the simulation. === Store Data from Simulink === All of the Simulink files in Paul Uhing's Research Repository output simulation data MATLAB structures contain the time and value arrays for important variables. After a simulation finishes these will show up as variables in the MATLAB Workspace. If you want to save any of these values for latter use select them in the MATLAB Workspace and right-click and select save or press ctrl+s to save these variables to a ''.mat'' file. == Understanding and Modifying RADA Simulations == The Simulink models of RADA for Paul Uhing's Thesis is built to be fairly easy to understand. Normal Simulink blocks are used for routing signals and completing simple calculations. For more difficult calculations MATLAB Function blocks are used. These blocks allow you to write MATLAB code to complete some calculation. They can have inputs from the Simulink simulation and parameter inputs from the MATLAB Workspace. This makes complex calculations much easier to understand. The goal of using all of these tricks is to avoid creating a model that is a rat's nest of interconnecting blocks that is impossible trace any errors in the simulation. Understanding how the RADA model was put together wil help you understand how to modify this model and how to build your own models. === Components of the Model === The model is broken down into subsystems based off of sub-components of the actual system. There is a block for calculating the accelerations of RADA's body, two blocks for calculating the different actuator sets, producing commands to the system, and calculating intermediate values used by other blocks. ==== Body dynamics calculations ==== The body dynamics block (''RADA_BodyDynamcis_v2'') takes in Euler angle position and velocity of the pendulum (including yaw), the global velocity of the ground vehicle, the force produced by the propellers in the x body direction of the pendulum, the force produced by the propellers in the y body direction of the pendulum, and the force produced by each wheel. This block is a MATLAB Function block so it also has parameter inputs. For using MATLAB Function block is is important to never delete: %#codegen because this allows the MATLAB code to function in Simulink. The code inside the block is just the implementation of the final equation in Chapter 3.4 of Paul Uhing's Thesis. The outputs of the block are the acceleration of the pendulum's in pitch and roll, the acceleration of the yaw of the system, and the x and y global acceleration of the ground robot. Then MATLAB continuous time integrator blocks are used to get the corresponding velocities and positions. MATLAB function blocks do not do integration very well so it is easier just to calculate the accelerations and then use the Simulink blocks to integrate. == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] Simulink comes with MATLAB. You should get MATLAB 2014b or latter to ensure the Simulink files from Paul Uhing's research repository will work with your installation of MATLAB. Once the install is complete and MATLAB is registered you can open MATLAB up. Then change the folder MATLAB will work out of to a directory you will want to work form. It would be best to copy a few files from Paul Uhing's repository to help you get started. Inside of the RADA Research Repository go to ''MATLAB/RADA'' and copy ''modelParams_smallWheels_RADA.m'', ''Hbrigeest.mat'', ''Kvw_calc.mat'', ''Hmu_r_erisLargeWheels.mat'', ''LQI_recalc.m'', and ''RADA_ctrlSep.m'' from this directory to you new diectroy as these files will allow you to load the model parameters and controller designs used in Paul Uhing's thesis or find the most recent version of these files an copy them instead. It would also be good to copy and of the ''RADA_psiCtrl_v2.slx'' or ''RADA_psiCtrl_LQGsep.slx'' files here to sever as the base RADA simulation in your new directory. Finally, open te ''DataSets'' directory below the ''RADA'' directory can copy one of the ''RADA_LQG_compPID.mat'' files or ''RADA_LQG_sep.mat'' files because it will allow you to have input vector for the copied ''.slx'' Simulink file. === Setting up the MATLAB Workspace === Now in MATLAB with you working directory set to you new directory for test RADA simulations run ''modelParams_smallWheels_RADA.m'' from the MATLAB command line ten load the RADA ''.mat'' data file. Now in the Current Folder screen in MATLAB double click on the ''.slx'' and wait for it to open. === Settings in Simulink === When running a simulation RADA in simulink always make sure your solver is set to '''ode23t'''! The RADA model is a moderately stiff set of differential equations and ode45 the default solver will take an extremely long time to run simulaitons of RADA. You can set the run length to any length you want and then run the simulation. === Store Data from Simulink === All of the Simulink files in Paul Uhing's Research Repository output simulation data MATLAB structures contain the time and value arrays for important variables. After a simulation finishes these will show up as variables in the MATLAB Workspace. If you want to save any of these values for latter use select them in the MATLAB Workspace and right-click and select save or press ctrl+s to save these variables to a ''.mat'' file. == Understanding and Modifying RADA Simulations == The Simulink models of RADA for Paul Uhing's Thesis is built to be fairly easy to understand. Normal Simulink blocks are used for routing signals and completing simple calculations. For more difficult calculations MATLAB Function blocks are used. These blocks allow you to write MATLAB code to complete some calculation. They can have inputs from the Simulink simulation and parameter inputs from the MATLAB Workspace. This makes complex calculations much easier to understand. The goal of using all of these tricks is to avoid creating a model that is a rat's nest of interconnecting blocks that is impossible trace any errors in the simulation. Understanding how the RADA model was put together wil help you understand how to modify this model and how to build your own models. === Components of the Model === The model is broken down into subsystems based off of sub-components of the actual system. There is a block for calculating the accelerations of RADA's body, two blocks for calculating the different actuator sets, producing commands to the system, and calculating intermediate values used by other blocks. ==== Body dynamics calculations ==== The body dynamics block (''RADA_BodyDynamcis_v2'') takes in Euler angle position and velocity of the pendulum (including yaw), the global velocity of the ground vehicle, the force produced by the propellers in the x body direction of the pendulum, the force produced by the propellers in the y body direction of the pendulum, and the force produced by each wheel. This block is a MATLAB Function block so it also has parameter inputs. For using MATLAB Function block is is important to never delete: %#codegen because this allows the MATLAB code to function in Simulink. The code inside the block is just the implementation of the final equation in Chapter 3.4 of Paul Uhing's Thesis. The outputs of the block are the acceleration of the pendulum's in pitch and roll, the acceleration of the yaw of the system, and the x and y global acceleration of the ground robot. Then MATLAB continuous time integrator blocks are used to get the corresponding velocities and positions. MATLAB function blocks do not do integration very well so it is easier just to calculate the accelerations and then use the Simulink blocks to integrate. ==== Actuator dynamics calculations ==== ==== System commands ==== ==== Body velocity calculations ==== === Modifying Simulink === ==== Creating a new simulation ==== ==== Modifying existing files ==== ==== System commands ==== ==== Body velocity calculations ==== === Modifying Simulink === ==== Creating a new simulation ==== ==== Modifying existing files ==== e1f4037393136571e48d31a560777f1ef493b0b5 288 287 2016-08-08T17:30:33Z Pfuhing 5 /* Actuator dynamics calculations */ wikitext text/x-wiki == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] Simulink comes with MATLAB. You should get MATLAB 2014b or latter to ensure the Simulink files from Paul Uhing's research repository will work with your installation of MATLAB. Once the install is complete and MATLAB is registered you can open MATLAB up. Then change the folder MATLAB will work out of to a directory you will want to work form. It would be best to copy a few files from Paul Uhing's repository to help you get started. Inside of the RADA Research Repository go to ''MATLAB/RADA'' and copy ''modelParams_smallWheels_RADA.m'', ''Hbrigeest.mat'', ''Kvw_calc.mat'', ''Hmu_r_erisLargeWheels.mat'', ''LQI_recalc.m'', and ''RADA_ctrlSep.m'' from this directory to you new diectroy as these files will allow you to load the model parameters and controller designs used in Paul Uhing's thesis or find the most recent version of these files an copy them instead. It would also be good to copy and of the ''RADA_psiCtrl_v2.slx'' or ''RADA_psiCtrl_LQGsep.slx'' files here to sever as the base RADA simulation in your new directory. Finally, open te ''DataSets'' directory below the ''RADA'' directory can copy one of the ''RADA_LQG_compPID.mat'' files or ''RADA_LQG_sep.mat'' files because it will allow you to have input vector for the copied ''.slx'' Simulink file. === Setting up the MATLAB Workspace === Now in MATLAB with you working directory set to you new directory for test RADA simulations run ''modelParams_smallWheels_RADA.m'' from the MATLAB command line ten load the RADA ''.mat'' data file. Now in the Current Folder screen in MATLAB double click on the ''.slx'' and wait for it to open. === Settings in Simulink === When running a simulation RADA in simulink always make sure your solver is set to '''ode23t'''! The RADA model is a moderately stiff set of differential equations and ode45 the default solver will take an extremely long time to run simulaitons of RADA. You can set the run length to any length you want and then run the simulation. === Store Data from Simulink === All of the Simulink files in Paul Uhing's Research Repository output simulation data MATLAB structures contain the time and value arrays for important variables. After a simulation finishes these will show up as variables in the MATLAB Workspace. If you want to save any of these values for latter use select them in the MATLAB Workspace and right-click and select save or press ctrl+s to save these variables to a ''.mat'' file. == Understanding and Modifying RADA Simulations == The Simulink models of RADA for Paul Uhing's Thesis is built to be fairly easy to understand. Normal Simulink blocks are used for routing signals and completing simple calculations. For more difficult calculations MATLAB Function blocks are used. These blocks allow you to write MATLAB code to complete some calculation. They can have inputs from the Simulink simulation and parameter inputs from the MATLAB Workspace. This makes complex calculations much easier to understand. The goal of using all of these tricks is to avoid creating a model that is a rat's nest of interconnecting blocks that is impossible trace any errors in the simulation. Understanding how the RADA model was put together wil help you understand how to modify this model and how to build your own models. === Components of the Model === The model is broken down into subsystems based off of sub-components of the actual system. There is a block for calculating the accelerations of RADA's body, two blocks for calculating the different actuator sets, producing commands to the system, and calculating intermediate values used by other blocks. ==== Body dynamics calculations ==== The body dynamics block (''RADA_BodyDynamcis_v2'') takes in Euler angle position and velocity of the pendulum (including yaw), the global velocity of the ground vehicle, the force produced by the propellers in the x body direction of the pendulum, the force produced by the propellers in the y body direction of the pendulum, and the force produced by each wheel. This block is a MATLAB Function block so it also has parameter inputs. For using MATLAB Function block is is important to never delete: %#codegen because this allows the MATLAB code to function in Simulink. The code inside the block is just the implementation of the final equation in Chapter 3.4 of Paul Uhing's Thesis. The outputs of the block are the acceleration of the pendulum's in pitch and roll, the acceleration of the yaw of the system, and the x and y global acceleration of the ground robot. Then MATLAB continuous time integrator blocks are used to get the corresponding velocities and positions. MATLAB function blocks do not do integration very well so it is easier just to calculate the accelerations and then use the Simulink blocks to integrate. == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] Simulink comes with MATLAB. You should get MATLAB 2014b or latter to ensure the Simulink files from Paul Uhing's research repository will work with your installation of MATLAB. Once the install is complete and MATLAB is registered you can open MATLAB up. Then change the folder MATLAB will work out of to a directory you will want to work form. It would be best to copy a few files from Paul Uhing's repository to help you get started. Inside of the RADA Research Repository go to ''MATLAB/RADA'' and copy ''modelParams_smallWheels_RADA.m'', ''Hbrigeest.mat'', ''Kvw_calc.mat'', ''Hmu_r_erisLargeWheels.mat'', ''LQI_recalc.m'', and ''RADA_ctrlSep.m'' from this directory to you new diectroy as these files will allow you to load the model parameters and controller designs used in Paul Uhing's thesis or find the most recent version of these files an copy them instead. It would also be good to copy and of the ''RADA_psiCtrl_v2.slx'' or ''RADA_psiCtrl_LQGsep.slx'' files here to sever as the base RADA simulation in your new directory. Finally, open te ''DataSets'' directory below the ''RADA'' directory can copy one of the ''RADA_LQG_compPID.mat'' files or ''RADA_LQG_sep.mat'' files because it will allow you to have input vector for the copied ''.slx'' Simulink file. === Setting up the MATLAB Workspace === Now in MATLAB with you working directory set to you new directory for test RADA simulations run ''modelParams_smallWheels_RADA.m'' from the MATLAB command line ten load the RADA ''.mat'' data file. Now in the Current Folder screen in MATLAB double click on the ''.slx'' and wait for it to open. === Settings in Simulink === When running a simulation RADA in simulink always make sure your solver is set to '''ode23t'''! The RADA model is a moderately stiff set of differential equations and ode45 the default solver will take an extremely long time to run simulaitons of RADA. You can set the run length to any length you want and then run the simulation. === Store Data from Simulink === All of the Simulink files in Paul Uhing's Research Repository output simulation data MATLAB structures contain the time and value arrays for important variables. After a simulation finishes these will show up as variables in the MATLAB Workspace. If you want to save any of these values for latter use select them in the MATLAB Workspace and right-click and select save or press ctrl+s to save these variables to a ''.mat'' file. == Understanding and Modifying RADA Simulations == The Simulink models of RADA for Paul Uhing's Thesis is built to be fairly easy to understand. Normal Simulink blocks are used for routing signals and completing simple calculations. For more difficult calculations MATLAB Function blocks are used. These blocks allow you to write MATLAB code to complete some calculation. They can have inputs from the Simulink simulation and parameter inputs from the MATLAB Workspace. This makes complex calculations much easier to understand. The goal of using all of these tricks is to avoid creating a model that is a rat's nest of interconnecting blocks that is impossible trace any errors in the simulation. Understanding how the RADA model was put together wil help you understand how to modify this model and how to build your own models. === Components of the Model === The model is broken down into subsystems based off of sub-components of the actual system. There is a block for calculating the accelerations of RADA's body, two blocks for calculating the different actuator sets, producing commands to the system, and calculating intermediate values used by other blocks. ==== Body dynamics calculations ==== The body dynamics block (''RADA_BodyDynamcis_v2'') takes in Euler angle position and velocity of the pendulum (including yaw), the global velocity of the ground vehicle, the force produced by the propellers in the x body direction of the pendulum, the force produced by the propellers in the y body direction of the pendulum, and the force produced by each wheel. This block is a MATLAB Function block so it also has parameter inputs. For using MATLAB Function block is is important to never delete: %#codegen because this allows the MATLAB code to function in Simulink. The code inside the block is just the implementation of the final equation in Chapter 3.4 of Paul Uhing's Thesis. The outputs of the block are the acceleration of the pendulum's in pitch and roll, the acceleration of the yaw of the system, and the x and y global acceleration of the ground robot. Then MATLAB continuous time integrator blocks are used to get the corresponding velocities and positions. MATLAB function blocks do not do integration very well so it is easier just to calculate the accelerations and then use the Simulink blocks to integrate. ==== Actuator dynamics calculations ==== The actuator dynamics in general take in commands from the controller, mix them into individual motor commands and then calculate the force outputs of the motors. There are two actuator dynamics calculation subsystems. One for the propellers and one for the wheels. ===== Propellers ===== The propeller subsystem takes in the the pitch and roll commands, the Euler angle velocities, the cart body velocities and the pitch and roll position. The pitch and roll inputs are mixed into actual motor commands using the ''Pitch_mixer'' and ''Roll_mixer''. These two MATLAB function blocks transform the command into something that can be used by the motor normalized between zero and one. Then the motor command, battery voltage and current motor velocity is passed into the motor MATLAB function blocks. These blocks calculate the acceleration of the propeller motors. That acceleration is integrated and the motor velocity is feedback into the motor block and then sent to the ''motor to force'' block. This MATLAB Function block uses the four propeller velocities, the angular velocities of the pendulum, and the body velocities of the cart. The output of the block is the total force output in the x and y pendulum axis. Finally there is a MATLAB function block, ''localAngleVel'' will calculate convert the global Euler angle velocities to to local body angular velocities. For how the model is generally used this last block isn't necessary but if you are going to have the pendulum do any maneuvers with large angular changes in both pitch and roll using this block will give you better results. The calculations for all of this blocks come from Chapters 2.2, 3.6 and 3.7 of Paul Uhing's Thesis. ===== Wheels ===== ==== System commands ==== ==== Body velocity calculations ==== === Modifying Simulink === ==== Creating a new simulation ==== ==== Modifying existing files ==== ==== System commands ==== ==== Body velocity calculations ==== === Modifying Simulink === ==== Creating a new simulation ==== ==== Modifying existing files ==== 792b1393ee1bdf03dbde1b54ba9389e1a48f8949 289 288 2016-08-08T17:31:36Z Pfuhing 5 wikitext text/x-wiki == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] Simulink comes with MATLAB. You should get MATLAB 2014b or latter to ensure the Simulink files from Paul Uhing's research repository will work with your installation of MATLAB. Once the install is complete and MATLAB is registered you can open MATLAB up. Then change the folder MATLAB will work out of to a directory you will want to work form. It would be best to copy a few files from Paul Uhing's repository to help you get started. Inside of the RADA Research Repository go to ''MATLAB/RADA'' and copy ''modelParams_smallWheels_RADA.m'', ''Hbrigeest.mat'', ''Kvw_calc.mat'', ''Hmu_r_erisLargeWheels.mat'', ''LQI_recalc.m'', and ''RADA_ctrlSep.m'' from this directory to you new diectroy as these files will allow you to load the model parameters and controller designs used in Paul Uhing's thesis or find the most recent version of these files an copy them instead. It would also be good to copy and of the ''RADA_psiCtrl_v2.slx'' or ''RADA_psiCtrl_LQGsep.slx'' files here to sever as the base RADA simulation in your new directory. Finally, open te ''DataSets'' directory below the ''RADA'' directory can copy one of the ''RADA_LQG_compPID.mat'' files or ''RADA_LQG_sep.mat'' files because it will allow you to have input vector for the copied ''.slx'' Simulink file. === Setting up the MATLAB Workspace === Now in MATLAB with you working directory set to you new directory for test RADA simulations run ''modelParams_smallWheels_RADA.m'' from the MATLAB command line ten load the RADA ''.mat'' data file. Now in the Current Folder screen in MATLAB double click on the ''.slx'' and wait for it to open. === Settings in Simulink === When running a simulation RADA in simulink always make sure your solver is set to '''ode23t'''! The RADA model is a moderately stiff set of differential equations and ode45 the default solver will take an extremely long time to run simulaitons of RADA. You can set the run length to any length you want and then run the simulation. === Store Data from Simulink === All of the Simulink files in Paul Uhing's Research Repository output simulation data MATLAB structures contain the time and value arrays for important variables. After a simulation finishes these will show up as variables in the MATLAB Workspace. If you want to save any of these values for latter use select them in the MATLAB Workspace and right-click and select save or press ctrl+s to save these variables to a ''.mat'' file. == Understanding and Modifying RADA Simulations == The Simulink models of RADA for Paul Uhing's Thesis is built to be fairly easy to understand. Normal Simulink blocks are used for routing signals and completing simple calculations. For more difficult calculations MATLAB Function blocks are used. These blocks allow you to write MATLAB code to complete some calculation. They can have inputs from the Simulink simulation and parameter inputs from the MATLAB Workspace. This makes complex calculations much easier to understand. The goal of using all of these tricks is to avoid creating a model that is a rat's nest of interconnecting blocks that is impossible trace any errors in the simulation. Understanding how the RADA model was put together wil help you understand how to modify this model and how to build your own models. === Components of the Model === The model is broken down into subsystems based off of sub-components of the actual system. There is a block for calculating the accelerations of RADA's body, two blocks for calculating the different actuator sets, producing commands to the system, and calculating intermediate values used by other blocks. ==== Body dynamics calculations ==== The body dynamics block (''RADA_BodyDynamcis_v2'') takes in Euler angle position and velocity of the pendulum (including yaw), the global velocity of the ground vehicle, the force produced by the propellers in the x body direction of the pendulum, the force produced by the propellers in the y body direction of the pendulum, and the force produced by each wheel. This block is a MATLAB Function block so it also has parameter inputs. For using MATLAB Function block is is important to never delete: %#codegen because this allows the MATLAB code to function in Simulink. The code inside the block is just the implementation of the final equation in Chapter 3.4 of Paul Uhing's Thesis. The outputs of the block are the acceleration of the pendulum's in pitch and roll, the acceleration of the yaw of the system, and the x and y global acceleration of the ground robot. Then MATLAB continuous time integrator blocks are used to get the corresponding velocities and positions. MATLAB function blocks do not do integration very well so it is easier just to calculate the accelerations and then use the Simulink blocks to integrate. == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] Simulink comes with MATLAB. You should get MATLAB 2014b or latter to ensure the Simulink files from Paul Uhing's research repository will work with your installation of MATLAB. Once the install is complete and MATLAB is registered you can open MATLAB up. Then change the folder MATLAB will work out of to a directory you will want to work form. It would be best to copy a few files from Paul Uhing's repository to help you get started. Inside of the RADA Research Repository go to ''MATLAB/RADA'' and copy ''modelParams_smallWheels_RADA.m'', ''Hbrigeest.mat'', ''Kvw_calc.mat'', ''Hmu_r_erisLargeWheels.mat'', ''LQI_recalc.m'', and ''RADA_ctrlSep.m'' from this directory to you new diectroy as these files will allow you to load the model parameters and controller designs used in Paul Uhing's thesis or find the most recent version of these files an copy them instead. It would also be good to copy and of the ''RADA_psiCtrl_v2.slx'' or ''RADA_psiCtrl_LQGsep.slx'' files here to sever as the base RADA simulation in your new directory. Finally, open te ''DataSets'' directory below the ''RADA'' directory can copy one of the ''RADA_LQG_compPID.mat'' files or ''RADA_LQG_sep.mat'' files because it will allow you to have input vector for the copied ''.slx'' Simulink file. === Setting up the MATLAB Workspace === Now in MATLAB with you working directory set to you new directory for test RADA simulations run ''modelParams_smallWheels_RADA.m'' from the MATLAB command line ten load the RADA ''.mat'' data file. Now in the Current Folder screen in MATLAB double click on the ''.slx'' and wait for it to open. === Settings in Simulink === When running a simulation RADA in simulink always make sure your solver is set to '''ode23t'''! The RADA model is a moderately stiff set of differential equations and ode45 the default solver will take an extremely long time to run simulaitons of RADA. You can set the run length to any length you want and then run the simulation. === Store Data from Simulink === All of the Simulink files in Paul Uhing's Research Repository output simulation data MATLAB structures contain the time and value arrays for important variables. After a simulation finishes these will show up as variables in the MATLAB Workspace. If you want to save any of these values for latter use select them in the MATLAB Workspace and right-click and select save or press ctrl+s to save these variables to a ''.mat'' file. == Understanding and Modifying RADA Simulations == The Simulink models of RADA for Paul Uhing's Thesis is built to be fairly easy to understand. Normal Simulink blocks are used for routing signals and completing simple calculations. For more difficult calculations MATLAB Function blocks are used. These blocks allow you to write MATLAB code to complete some calculation. They can have inputs from the Simulink simulation and parameter inputs from the MATLAB Workspace. This makes complex calculations much easier to understand. The goal of using all of these tricks is to avoid creating a model that is a rat's nest of interconnecting blocks that is impossible trace any errors in the simulation. Understanding how the RADA model was put together wil help you understand how to modify this model and how to build your own models. === Components of the Model === The model is broken down into subsystems based off of sub-components of the actual system. There is a block for calculating the accelerations of RADA's body, two blocks for calculating the different actuator sets, producing commands to the system, and calculating intermediate values used by other blocks. ==== Body dynamics calculations ==== The body dynamics block (''RADA_BodyDynamcis_v2'') takes in Euler angle position and velocity of the pendulum (including yaw), the global velocity of the ground vehicle, the force produced by the propellers in the x body direction of the pendulum, the force produced by the propellers in the y body direction of the pendulum, and the force produced by each wheel. This block is a MATLAB Function block so it also has parameter inputs. For using MATLAB Function block is is important to never delete: %#codegen because this allows the MATLAB code to function in Simulink. The code inside the block is just the implementation of the final equation in Chapter 3.4 of Paul Uhing's Thesis. The outputs of the block are the acceleration of the pendulum's in pitch and roll, the acceleration of the yaw of the system, and the x and y global acceleration of the ground robot. Then MATLAB continuous time integrator blocks are used to get the corresponding velocities and positions. MATLAB function blocks do not do integration very well so it is easier just to calculate the accelerations and then use the Simulink blocks to integrate. ==== Actuator dynamics calculations ==== The actuator dynamics in general take in commands from the controller, mix them into individual motor commands and then calculate the force outputs of the motors. There are two actuator dynamics calculation subsystems. One for the propellers and one for the wheels. ===== Propellers ===== The propeller subsystem takes in the the pitch and roll commands, the Euler angle velocities, the cart body velocities and the pitch and roll position. The pitch and roll inputs are mixed into actual motor commands using the ''Pitch_mixer'' and ''Roll_mixer''. These two MATLAB function blocks transform the command into something that can be used by the motor normalized between zero and one. Then the motor command, battery voltage and current motor velocity is passed into the motor MATLAB function blocks. These blocks calculate the acceleration of the propeller motors. That acceleration is integrated and the motor velocity is feedback into the motor block and then sent to the ''motor to force'' block. This MATLAB Function block uses the four propeller velocities, the angular velocities of the pendulum, and the body velocities of the cart. The output of the block is the total force output in the x and y pendulum axis. Finally there is a MATLAB function block, ''localAngleVel'' will calculate convert the global Euler angle velocities to to local body angular velocities. For how the model is generally used this last block isn't necessary but if you are going to have the pendulum do any maneuvers with large angular changes in both pitch and roll using this block will give you better results. The calculations for all of this blocks come from Chapters 2.2, 3.6 and 3.7 of Paul Uhing's Thesis. ===== Wheels ===== ==== System commands ==== ==== Body velocity calculations ==== === Modifying Simulink === ==== Creating a new simulation ==== ==== Modifying existing files ==== b25d2df62fd1bbdfd2e7ec69c550888d4e0a41d2 290 289 2016-08-08T17:54:12Z Pfuhing 5 /* Actuator dynamics calculations */ wikitext text/x-wiki == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] Simulink comes with MATLAB. You should get MATLAB 2014b or latter to ensure the Simulink files from Paul Uhing's research repository will work with your installation of MATLAB. Once the install is complete and MATLAB is registered you can open MATLAB up. Then change the folder MATLAB will work out of to a directory you will want to work form. It would be best to copy a few files from Paul Uhing's repository to help you get started. Inside of the RADA Research Repository go to ''MATLAB/RADA'' and copy ''modelParams_smallWheels_RADA.m'', ''Hbrigeest.mat'', ''Kvw_calc.mat'', ''Hmu_r_erisLargeWheels.mat'', ''LQI_recalc.m'', and ''RADA_ctrlSep.m'' from this directory to you new diectroy as these files will allow you to load the model parameters and controller designs used in Paul Uhing's thesis or find the most recent version of these files an copy them instead. It would also be good to copy and of the ''RADA_psiCtrl_v2.slx'' or ''RADA_psiCtrl_LQGsep.slx'' files here to sever as the base RADA simulation in your new directory. Finally, open te ''DataSets'' directory below the ''RADA'' directory can copy one of the ''RADA_LQG_compPID.mat'' files or ''RADA_LQG_sep.mat'' files because it will allow you to have input vector for the copied ''.slx'' Simulink file. === Setting up the MATLAB Workspace === Now in MATLAB with you working directory set to you new directory for test RADA simulations run ''modelParams_smallWheels_RADA.m'' from the MATLAB command line ten load the RADA ''.mat'' data file. Now in the Current Folder screen in MATLAB double click on the ''.slx'' and wait for it to open. === Settings in Simulink === When running a simulation RADA in simulink always make sure your solver is set to '''ode23t'''! The RADA model is a moderately stiff set of differential equations and ode45 the default solver will take an extremely long time to run simulaitons of RADA. You can set the run length to any length you want and then run the simulation. === Store Data from Simulink === All of the Simulink files in Paul Uhing's Research Repository output simulation data MATLAB structures contain the time and value arrays for important variables. After a simulation finishes these will show up as variables in the MATLAB Workspace. If you want to save any of these values for latter use select them in the MATLAB Workspace and right-click and select save or press ctrl+s to save these variables to a ''.mat'' file. == Understanding and Modifying RADA Simulations == The Simulink models of RADA for Paul Uhing's Thesis is built to be fairly easy to understand. Normal Simulink blocks are used for routing signals and completing simple calculations. For more difficult calculations MATLAB Function blocks are used. These blocks allow you to write MATLAB code to complete some calculation. They can have inputs from the Simulink simulation and parameter inputs from the MATLAB Workspace. This makes complex calculations much easier to understand. The goal of using all of these tricks is to avoid creating a model that is a rat's nest of interconnecting blocks that is impossible trace any errors in the simulation. Understanding how the RADA model was put together wil help you understand how to modify this model and how to build your own models. === Components of the Model === The model is broken down into subsystems based off of sub-components of the actual system. There is a block for calculating the accelerations of RADA's body, two blocks for calculating the different actuator sets, producing commands to the system, and calculating intermediate values used by other blocks. ==== Body dynamics calculations ==== The body dynamics block (''RADA_BodyDynamcis_v2'') takes in Euler angle position and velocity of the pendulum (including yaw), the global velocity of the ground vehicle, the force produced by the propellers in the x body direction of the pendulum, the force produced by the propellers in the y body direction of the pendulum, and the force produced by each wheel. This block is a MATLAB Function block so it also has parameter inputs. For using MATLAB Function block is is important to never delete: %#codegen because this allows the MATLAB code to function in Simulink. The code inside the block is just the implementation of the final equation in Chapter 3.4 of Paul Uhing's Thesis. The outputs of the block are the acceleration of the pendulum's in pitch and roll, the acceleration of the yaw of the system, and the x and y global acceleration of the ground robot. Then MATLAB continuous time integrator blocks are used to get the corresponding velocities and positions. MATLAB function blocks do not do integration very well so it is easier just to calculate the accelerations and then use the Simulink blocks to integrate. == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] Simulink comes with MATLAB. You should get MATLAB 2014b or latter to ensure the Simulink files from Paul Uhing's research repository will work with your installation of MATLAB. Once the install is complete and MATLAB is registered you can open MATLAB up. Then change the folder MATLAB will work out of to a directory you will want to work form. It would be best to copy a few files from Paul Uhing's repository to help you get started. Inside of the RADA Research Repository go to ''MATLAB/RADA'' and copy ''modelParams_smallWheels_RADA.m'', ''Hbrigeest.mat'', ''Kvw_calc.mat'', ''Hmu_r_erisLargeWheels.mat'', ''LQI_recalc.m'', and ''RADA_ctrlSep.m'' from this directory to you new diectroy as these files will allow you to load the model parameters and controller designs used in Paul Uhing's thesis or find the most recent version of these files an copy them instead. It would also be good to copy and of the ''RADA_psiCtrl_v2.slx'' or ''RADA_psiCtrl_LQGsep.slx'' files here to sever as the base RADA simulation in your new directory. Finally, open te ''DataSets'' directory below the ''RADA'' directory can copy one of the ''RADA_LQG_compPID.mat'' files or ''RADA_LQG_sep.mat'' files because it will allow you to have input vector for the copied ''.slx'' Simulink file. === Setting up the MATLAB Workspace === Now in MATLAB with you working directory set to you new directory for test RADA simulations run ''modelParams_smallWheels_RADA.m'' from the MATLAB command line ten load the RADA ''.mat'' data file. Now in the Current Folder screen in MATLAB double click on the ''.slx'' and wait for it to open. === Settings in Simulink === When running a simulation RADA in simulink always make sure your solver is set to '''ode23t'''! The RADA model is a moderately stiff set of differential equations and ode45 the default solver will take an extremely long time to run simulaitons of RADA. You can set the run length to any length you want and then run the simulation. === Store Data from Simulink === All of the Simulink files in Paul Uhing's Research Repository output simulation data MATLAB structures contain the time and value arrays for important variables. After a simulation finishes these will show up as variables in the MATLAB Workspace. If you want to save any of these values for latter use select them in the MATLAB Workspace and right-click and select save or press ctrl+s to save these variables to a ''.mat'' file. == Understanding and Modifying RADA Simulations == The Simulink models of RADA for Paul Uhing's Thesis is built to be fairly easy to understand. Normal Simulink blocks are used for routing signals and completing simple calculations. For more difficult calculations MATLAB Function blocks are used. These blocks allow you to write MATLAB code to complete some calculation. They can have inputs from the Simulink simulation and parameter inputs from the MATLAB Workspace. This makes complex calculations much easier to understand. The goal of using all of these tricks is to avoid creating a model that is a rat's nest of interconnecting blocks that is impossible trace any errors in the simulation. Understanding how the RADA model was put together wil help you understand how to modify this model and how to build your own models. === Components of the Model === The model is broken down into subsystems based off of sub-components of the actual system. There is a block for calculating the accelerations of RADA's body, two blocks for calculating the different actuator sets, producing commands to the system, and calculating intermediate values used by other blocks. ==== Body dynamics calculations ==== The body dynamics block (''RADA_BodyDynamcis_v2'') takes in Euler angle position and velocity of the pendulum (including yaw), the global velocity of the ground vehicle, the force produced by the propellers in the x body direction of the pendulum, the force produced by the propellers in the y body direction of the pendulum, and the force produced by each wheel. This block is a MATLAB Function block so it also has parameter inputs. For using MATLAB Function block is is important to never delete: %#codegen because this allows the MATLAB code to function in Simulink. The code inside the block is just the implementation of the final equation in Chapter 3.4 of Paul Uhing's Thesis. The outputs of the block are the acceleration of the pendulum's in pitch and roll, the acceleration of the yaw of the system, and the x and y global acceleration of the ground robot. Then MATLAB continuous time integrator blocks are used to get the corresponding velocities and positions. MATLAB function blocks do not do integration very well so it is easier just to calculate the accelerations and then use the Simulink blocks to integrate. ==== Actuator dynamics calculations ==== The actuator dynamics in general take in commands from the controller, mix them into individual motor commands and then calculate the force outputs of the motors. There are two actuator dynamics calculation subsystems. One for the propellers and one for the wheels. The controller output is calculated before these blocks and after the input command block. You just put whatever controller you want to use. ===== Propellers ===== The propeller subsystem takes in the the pitch and roll commands, the Euler angle velocities, the cart body velocities and the pitch and roll position. The pitch and roll inputs are mixed into actual motor commands using the ''Pitch_mixer'' and ''Roll_mixer''. These two MATLAB function blocks transform the command into something that can be used by the motor normalized between zero and one. Then the motor command, battery voltage and current motor velocity is passed into the motor MATLAB function blocks. These blocks calculate the acceleration of the propeller motors. That acceleration is integrated and the motor velocity is feedback into the motor block and then sent to the ''motor to force'' block. This MATLAB Function block uses the four propeller velocities, the angular velocities of the pendulum, and the body velocities of the cart. The output of the block is the total force output in the x and y pendulum axis. Finally there is a MATLAB function block, ''localAngleVel'' will calculate convert the global Euler angle velocities to to local body angular velocities. For how the model is generally used this last block isn't necessary but if you are going to have the pendulum do any maneuvers with large angular changes in both pitch and roll using this block will give you better results. The calculations for all of this blocks come from Chapters 2.2, 3.6 and 3.7 of Paul Uhing's Thesis. ===== Wheels ===== The ''WheelForce'' subsystem of the RADA model takes in the heading, x and y controller outputs, the body linear velocities of the cart, the yaw velocity of the cart, the heading of the cart and finally takes in the x and y reference commands. This block then outputs the force produced by each of the four wheels. The heading controller output command, the x and y velocity commands, the heading of the robot, and finally the x and y reference velocities are put into the wheel command mixing matrix, ''Wheel input mixer''. If you are using PIDs you will want to force this heading input to be zero all the time. This block calculate the command that should be sent to each wheel. These wheel commands pass though some saturation and scaling blocks and then are passed into the ''H-bridge model'' MATLAB Function block. This converts the controller output to a command for the motor between -1 and 1. This command is passed into the ''motor'' subsystems. These blocks take in this command the battery voltage and the velocity of the wheel which was summed from the body linear velocities of the cart and yaw velocity. This subsystem uses Simulink blocks to calculate the force produced by each wheel. The calcaultions done in this subsystem can be found in Chapters 3.5 and 3.7 of Paul Uhing's Thesis. ==== System commands ==== ==== Body velocity calculations ==== === Modifying Simulink === ==== Creating a new simulation ==== ==== Modifying existing files ==== 23475f093d27abc3d1ea2f0b9f1671959766e093 291 290 2016-08-08T17:54:41Z Pfuhing 5 /* Body dynamics calculations */ wikitext text/x-wiki == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] Simulink comes with MATLAB. You should get MATLAB 2014b or latter to ensure the Simulink files from Paul Uhing's research repository will work with your installation of MATLAB. Once the install is complete and MATLAB is registered you can open MATLAB up. Then change the folder MATLAB will work out of to a directory you will want to work form. It would be best to copy a few files from Paul Uhing's repository to help you get started. Inside of the RADA Research Repository go to ''MATLAB/RADA'' and copy ''modelParams_smallWheels_RADA.m'', ''Hbrigeest.mat'', ''Kvw_calc.mat'', ''Hmu_r_erisLargeWheels.mat'', ''LQI_recalc.m'', and ''RADA_ctrlSep.m'' from this directory to you new diectroy as these files will allow you to load the model parameters and controller designs used in Paul Uhing's thesis or find the most recent version of these files an copy them instead. It would also be good to copy and of the ''RADA_psiCtrl_v2.slx'' or ''RADA_psiCtrl_LQGsep.slx'' files here to sever as the base RADA simulation in your new directory. Finally, open te ''DataSets'' directory below the ''RADA'' directory can copy one of the ''RADA_LQG_compPID.mat'' files or ''RADA_LQG_sep.mat'' files because it will allow you to have input vector for the copied ''.slx'' Simulink file. === Setting up the MATLAB Workspace === Now in MATLAB with you working directory set to you new directory for test RADA simulations run ''modelParams_smallWheels_RADA.m'' from the MATLAB command line ten load the RADA ''.mat'' data file. Now in the Current Folder screen in MATLAB double click on the ''.slx'' and wait for it to open. === Settings in Simulink === When running a simulation RADA in simulink always make sure your solver is set to '''ode23t'''! The RADA model is a moderately stiff set of differential equations and ode45 the default solver will take an extremely long time to run simulaitons of RADA. You can set the run length to any length you want and then run the simulation. === Store Data from Simulink === All of the Simulink files in Paul Uhing's Research Repository output simulation data MATLAB structures contain the time and value arrays for important variables. After a simulation finishes these will show up as variables in the MATLAB Workspace. If you want to save any of these values for latter use select them in the MATLAB Workspace and right-click and select save or press ctrl+s to save these variables to a ''.mat'' file. == Understanding and Modifying RADA Simulations == The Simulink models of RADA for Paul Uhing's Thesis is built to be fairly easy to understand. Normal Simulink blocks are used for routing signals and completing simple calculations. For more difficult calculations MATLAB Function blocks are used. These blocks allow you to write MATLAB code to complete some calculation. They can have inputs from the Simulink simulation and parameter inputs from the MATLAB Workspace. This makes complex calculations much easier to understand. The goal of using all of these tricks is to avoid creating a model that is a rat's nest of interconnecting blocks that is impossible trace any errors in the simulation. Understanding how the RADA model was put together wil help you understand how to modify this model and how to build your own models. === Components of the Model === The model is broken down into subsystems based off of sub-components of the actual system. There is a block for calculating the accelerations of RADA's body, two blocks for calculating the different actuator sets, producing commands to the system, and calculating intermediate values used by other blocks. ==== Body dynamics calculations ==== The body dynamics block (''RADA_BodyDynamcis_v2'') takes in Euler angle position and velocity of the pendulum (including yaw), the global velocity of the ground vehicle, the force produced by the propellers in the x body direction of the pendulum, the force produced by the propellers in the y body direction of the pendulum, and the force produced by each wheel. This block is a MATLAB Function block so it also has parameter inputs. For using MATLAB Function block is is important to never delete: %#codegen because this allows the MATLAB code to function in Simulink. The code inside the block is just the implementation of the final equation in Chapter 3.4 of Paul Uhing's Thesis. The outputs of the block are the acceleration of the pendulum's in pitch and roll, the acceleration of the yaw of the system, and the x and y global acceleration of the ground robot. Then MATLAB continuous time integrator blocks are used to get the corresponding velocities and positions. MATLAB function blocks do not do integration very well so it is easier just to calculate the accelerations and then use the Simulink blocks to integrate. == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] Simulink comes with MATLAB. You should get MATLAB 2014b or latter to ensure the Simulink files from Paul Uhing's research repository will work with your installation of MATLAB. Once the install is complete and MATLAB is registered you can open MATLAB up. Then change the folder MATLAB will work out of to a directory you will want to work form. It would be best to copy a few files from Paul Uhing's repository to help you get started. Inside of the RADA Research Repository go to ''MATLAB/RADA'' and copy ''modelParams_smallWheels_RADA.m'', ''Hbrigeest.mat'', ''Kvw_calc.mat'', ''Hmu_r_erisLargeWheels.mat'', ''LQI_recalc.m'', and ''RADA_ctrlSep.m'' from this directory to you new diectroy as these files will allow you to load the model parameters and controller designs used in Paul Uhing's thesis or find the most recent version of these files an copy them instead. It would also be good to copy and of the ''RADA_psiCtrl_v2.slx'' or ''RADA_psiCtrl_LQGsep.slx'' files here to sever as the base RADA simulation in your new directory. Finally, open te ''DataSets'' directory below the ''RADA'' directory can copy one of the ''RADA_LQG_compPID.mat'' files or ''RADA_LQG_sep.mat'' files because it will allow you to have input vector for the copied ''.slx'' Simulink file. === Setting up the MATLAB Workspace === Now in MATLAB with you working directory set to you new directory for test RADA simulations run ''modelParams_smallWheels_RADA.m'' from the MATLAB command line ten load the RADA ''.mat'' data file. Now in the Current Folder screen in MATLAB double click on the ''.slx'' and wait for it to open. === Settings in Simulink === When running a simulation RADA in simulink always make sure your solver is set to '''ode23t'''! The RADA model is a moderately stiff set of differential equations and ode45 the default solver will take an extremely long time to run simulaitons of RADA. You can set the run length to any length you want and then run the simulation. === Store Data from Simulink === All of the Simulink files in Paul Uhing's Research Repository output simulation data MATLAB structures contain the time and value arrays for important variables. After a simulation finishes these will show up as variables in the MATLAB Workspace. If you want to save any of these values for latter use select them in the MATLAB Workspace and right-click and select save or press ctrl+s to save these variables to a ''.mat'' file. == Understanding and Modifying RADA Simulations == The Simulink models of RADA for Paul Uhing's Thesis is built to be fairly easy to understand. Normal Simulink blocks are used for routing signals and completing simple calculations. For more difficult calculations MATLAB Function blocks are used. These blocks allow you to write MATLAB code to complete some calculation. They can have inputs from the Simulink simulation and parameter inputs from the MATLAB Workspace. This makes complex calculations much easier to understand. The goal of using all of these tricks is to avoid creating a model that is a rat's nest of interconnecting blocks that is impossible trace any errors in the simulation. Understanding how the RADA model was put together wil help you understand how to modify this model and how to build your own models. === Components of the Model === The model is broken down into subsystems based off of sub-components of the actual system. There is a block for calculating the accelerations of RADA's body, two blocks for calculating the different actuator sets, producing commands to the system, and calculating intermediate values used by other blocks. ==== Body dynamics calculations ==== The body dynamics block (''RADA_BodyDynamcis_v2'') takes in Euler angle position and velocity of the pendulum (including yaw), the global velocity of the ground vehicle, the force produced by the propellers in the x body direction of the pendulum, the force produced by the propellers in the y body direction of the pendulum, and the force produced by each wheel. This block is a MATLAB Function block so it also has parameter inputs. For using MATLAB Function block is is important to never delete: %#codegen because this allows the MATLAB code to function in Simulink. The code inside the block is just the implementation of the final equation in Chapter 3.4 and 3.5 of Paul Uhing's Thesis. The outputs of the block are the acceleration of the pendulum's in pitch and roll, the acceleration of the yaw of the system, and the x and y global acceleration of the ground robot. Then MATLAB continuous time integrator blocks are used to get the corresponding velocities and positions. MATLAB function blocks do not do integration very well so it is easier just to calculate the accelerations and then use the Simulink blocks to integrate. ==== Actuator dynamics calculations ==== The actuator dynamics in general take in commands from the controller, mix them into individual motor commands and then calculate the force outputs of the motors. There are two actuator dynamics calculation subsystems. One for the propellers and one for the wheels. The controller output is calculated before these blocks and after the input command block. You just put whatever controller you want to use. ===== Propellers ===== The propeller subsystem takes in the the pitch and roll commands, the Euler angle velocities, the cart body velocities and the pitch and roll position. The pitch and roll inputs are mixed into actual motor commands using the ''Pitch_mixer'' and ''Roll_mixer''. These two MATLAB function blocks transform the command into something that can be used by the motor normalized between zero and one. Then the motor command, battery voltage and current motor velocity is passed into the motor MATLAB function blocks. These blocks calculate the acceleration of the propeller motors. That acceleration is integrated and the motor velocity is feedback into the motor block and then sent to the ''motor to force'' block. This MATLAB Function block uses the four propeller velocities, the angular velocities of the pendulum, and the body velocities of the cart. The output of the block is the total force output in the x and y pendulum axis. Finally there is a MATLAB function block, ''localAngleVel'' will calculate convert the global Euler angle velocities to to local body angular velocities. For how the model is generally used this last block isn't necessary but if you are going to have the pendulum do any maneuvers with large angular changes in both pitch and roll using this block will give you better results. The calculations for all of this blocks come from Chapters 2.2, 3.6 and 3.7 of Paul Uhing's Thesis. ===== Wheels ===== The ''WheelForce'' subsystem of the RADA model takes in the heading, x and y controller outputs, the body linear velocities of the cart, the yaw velocity of the cart, the heading of the cart and finally takes in the x and y reference commands. This block then outputs the force produced by each of the four wheels. The heading controller output command, the x and y velocity commands, the heading of the robot, and finally the x and y reference velocities are put into the wheel command mixing matrix, ''Wheel input mixer''. If you are using PIDs you will want to force this heading input to be zero all the time. This block calculate the command that should be sent to each wheel. These wheel commands pass though some saturation and scaling blocks and then are passed into the ''H-bridge model'' MATLAB Function block. This converts the controller output to a command for the motor between -1 and 1. This command is passed into the ''motor'' subsystems. These blocks take in this command the battery voltage and the velocity of the wheel which was summed from the body linear velocities of the cart and yaw velocity. This subsystem uses Simulink blocks to calculate the force produced by each wheel. The calcaultions done in this subsystem can be found in Chapters 3.5 and 3.7 of Paul Uhing's Thesis. ==== System commands ==== ==== Body velocity calculations ==== === Modifying Simulink === ==== Creating a new simulation ==== ==== Modifying existing files ==== 560b2760b721bb9f5f01467eda04171fcd2bfd7c 292 291 2016-08-08T17:56:47Z Pfuhing 5 /* System commands */ wikitext text/x-wiki == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] Simulink comes with MATLAB. You should get MATLAB 2014b or latter to ensure the Simulink files from Paul Uhing's research repository will work with your installation of MATLAB. Once the install is complete and MATLAB is registered you can open MATLAB up. Then change the folder MATLAB will work out of to a directory you will want to work form. It would be best to copy a few files from Paul Uhing's repository to help you get started. Inside of the RADA Research Repository go to ''MATLAB/RADA'' and copy ''modelParams_smallWheels_RADA.m'', ''Hbrigeest.mat'', ''Kvw_calc.mat'', ''Hmu_r_erisLargeWheels.mat'', ''LQI_recalc.m'', and ''RADA_ctrlSep.m'' from this directory to you new diectroy as these files will allow you to load the model parameters and controller designs used in Paul Uhing's thesis or find the most recent version of these files an copy them instead. It would also be good to copy and of the ''RADA_psiCtrl_v2.slx'' or ''RADA_psiCtrl_LQGsep.slx'' files here to sever as the base RADA simulation in your new directory. Finally, open te ''DataSets'' directory below the ''RADA'' directory can copy one of the ''RADA_LQG_compPID.mat'' files or ''RADA_LQG_sep.mat'' files because it will allow you to have input vector for the copied ''.slx'' Simulink file. === Setting up the MATLAB Workspace === Now in MATLAB with you working directory set to you new directory for test RADA simulations run ''modelParams_smallWheels_RADA.m'' from the MATLAB command line ten load the RADA ''.mat'' data file. Now in the Current Folder screen in MATLAB double click on the ''.slx'' and wait for it to open. === Settings in Simulink === When running a simulation RADA in simulink always make sure your solver is set to '''ode23t'''! The RADA model is a moderately stiff set of differential equations and ode45 the default solver will take an extremely long time to run simulaitons of RADA. You can set the run length to any length you want and then run the simulation. === Store Data from Simulink === All of the Simulink files in Paul Uhing's Research Repository output simulation data MATLAB structures contain the time and value arrays for important variables. After a simulation finishes these will show up as variables in the MATLAB Workspace. If you want to save any of these values for latter use select them in the MATLAB Workspace and right-click and select save or press ctrl+s to save these variables to a ''.mat'' file. == Understanding and Modifying RADA Simulations == The Simulink models of RADA for Paul Uhing's Thesis is built to be fairly easy to understand. Normal Simulink blocks are used for routing signals and completing simple calculations. For more difficult calculations MATLAB Function blocks are used. These blocks allow you to write MATLAB code to complete some calculation. They can have inputs from the Simulink simulation and parameter inputs from the MATLAB Workspace. This makes complex calculations much easier to understand. The goal of using all of these tricks is to avoid creating a model that is a rat's nest of interconnecting blocks that is impossible trace any errors in the simulation. Understanding how the RADA model was put together wil help you understand how to modify this model and how to build your own models. === Components of the Model === The model is broken down into subsystems based off of sub-components of the actual system. There is a block for calculating the accelerations of RADA's body, two blocks for calculating the different actuator sets, producing commands to the system, and calculating intermediate values used by other blocks. ==== Body dynamics calculations ==== The body dynamics block (''RADA_BodyDynamcis_v2'') takes in Euler angle position and velocity of the pendulum (including yaw), the global velocity of the ground vehicle, the force produced by the propellers in the x body direction of the pendulum, the force produced by the propellers in the y body direction of the pendulum, and the force produced by each wheel. This block is a MATLAB Function block so it also has parameter inputs. For using MATLAB Function block is is important to never delete: %#codegen because this allows the MATLAB code to function in Simulink. The code inside the block is just the implementation of the final equation in Chapter 3.4 of Paul Uhing's Thesis. The outputs of the block are the acceleration of the pendulum's in pitch and roll, the acceleration of the yaw of the system, and the x and y global acceleration of the ground robot. Then MATLAB continuous time integrator blocks are used to get the corresponding velocities and positions. MATLAB function blocks do not do integration very well so it is easier just to calculate the accelerations and then use the Simulink blocks to integrate. == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] Simulink comes with MATLAB. You should get MATLAB 2014b or latter to ensure the Simulink files from Paul Uhing's research repository will work with your installation of MATLAB. Once the install is complete and MATLAB is registered you can open MATLAB up. Then change the folder MATLAB will work out of to a directory you will want to work form. It would be best to copy a few files from Paul Uhing's repository to help you get started. Inside of the RADA Research Repository go to ''MATLAB/RADA'' and copy ''modelParams_smallWheels_RADA.m'', ''Hbrigeest.mat'', ''Kvw_calc.mat'', ''Hmu_r_erisLargeWheels.mat'', ''LQI_recalc.m'', and ''RADA_ctrlSep.m'' from this directory to you new diectroy as these files will allow you to load the model parameters and controller designs used in Paul Uhing's thesis or find the most recent version of these files an copy them instead. It would also be good to copy and of the ''RADA_psiCtrl_v2.slx'' or ''RADA_psiCtrl_LQGsep.slx'' files here to sever as the base RADA simulation in your new directory. Finally, open te ''DataSets'' directory below the ''RADA'' directory can copy one of the ''RADA_LQG_compPID.mat'' files or ''RADA_LQG_sep.mat'' files because it will allow you to have input vector for the copied ''.slx'' Simulink file. === Setting up the MATLAB Workspace === Now in MATLAB with you working directory set to you new directory for test RADA simulations run ''modelParams_smallWheels_RADA.m'' from the MATLAB command line ten load the RADA ''.mat'' data file. Now in the Current Folder screen in MATLAB double click on the ''.slx'' and wait for it to open. === Settings in Simulink === When running a simulation RADA in simulink always make sure your solver is set to '''ode23t'''! The RADA model is a moderately stiff set of differential equations and ode45 the default solver will take an extremely long time to run simulaitons of RADA. You can set the run length to any length you want and then run the simulation. === Store Data from Simulink === All of the Simulink files in Paul Uhing's Research Repository output simulation data MATLAB structures contain the time and value arrays for important variables. After a simulation finishes these will show up as variables in the MATLAB Workspace. If you want to save any of these values for latter use select them in the MATLAB Workspace and right-click and select save or press ctrl+s to save these variables to a ''.mat'' file. == Understanding and Modifying RADA Simulations == The Simulink models of RADA for Paul Uhing's Thesis is built to be fairly easy to understand. Normal Simulink blocks are used for routing signals and completing simple calculations. For more difficult calculations MATLAB Function blocks are used. These blocks allow you to write MATLAB code to complete some calculation. They can have inputs from the Simulink simulation and parameter inputs from the MATLAB Workspace. This makes complex calculations much easier to understand. The goal of using all of these tricks is to avoid creating a model that is a rat's nest of interconnecting blocks that is impossible trace any errors in the simulation. Understanding how the RADA model was put together wil help you understand how to modify this model and how to build your own models. === Components of the Model === The model is broken down into subsystems based off of sub-components of the actual system. There is a block for calculating the accelerations of RADA's body, two blocks for calculating the different actuator sets, producing commands to the system, and calculating intermediate values used by other blocks. ==== Body dynamics calculations ==== The body dynamics block (''RADA_BodyDynamcis_v2'') takes in Euler angle position and velocity of the pendulum (including yaw), the global velocity of the ground vehicle, the force produced by the propellers in the x body direction of the pendulum, the force produced by the propellers in the y body direction of the pendulum, and the force produced by each wheel. This block is a MATLAB Function block so it also has parameter inputs. For using MATLAB Function block is is important to never delete: %#codegen because this allows the MATLAB code to function in Simulink. The code inside the block is just the implementation of the final equation in Chapter 3.4 and 3.5 of Paul Uhing's Thesis. The outputs of the block are the acceleration of the pendulum's in pitch and roll, the acceleration of the yaw of the system, and the x and y global acceleration of the ground robot. Then MATLAB continuous time integrator blocks are used to get the corresponding velocities and positions. MATLAB function blocks do not do integration very well so it is easier just to calculate the accelerations and then use the Simulink blocks to integrate. ==== Actuator dynamics calculations ==== The actuator dynamics in general take in commands from the controller, mix them into individual motor commands and then calculate the force outputs of the motors. There are two actuator dynamics calculation subsystems. One for the propellers and one for the wheels. The controller output is calculated before these blocks and after the input command block. You just put whatever controller you want to use. ===== Propellers ===== The propeller subsystem takes in the the pitch and roll commands, the Euler angle velocities, the cart body velocities and the pitch and roll position. The pitch and roll inputs are mixed into actual motor commands using the ''Pitch_mixer'' and ''Roll_mixer''. These two MATLAB function blocks transform the command into something that can be used by the motor normalized between zero and one. Then the motor command, battery voltage and current motor velocity is passed into the motor MATLAB function blocks. These blocks calculate the acceleration of the propeller motors. That acceleration is integrated and the motor velocity is feedback into the motor block and then sent to the ''motor to force'' block. This MATLAB Function block uses the four propeller velocities, the angular velocities of the pendulum, and the body velocities of the cart. The output of the block is the total force output in the x and y pendulum axis. Finally there is a MATLAB function block, ''localAngleVel'' will calculate convert the global Euler angle velocities to to local body angular velocities. For how the model is generally used this last block isn't necessary but if you are going to have the pendulum do any maneuvers with large angular changes in both pitch and roll using this block will give you better results. The calculations for all of this blocks come from Chapters 2.2, 3.6 and 3.7 of Paul Uhing's Thesis. ===== Wheels ===== The ''WheelForce'' subsystem of the RADA model takes in the heading, x and y controller outputs, the body linear velocities of the cart, the yaw velocity of the cart, the heading of the cart and finally takes in the x and y reference commands. This block then outputs the force produced by each of the four wheels. The heading controller output command, the x and y velocity commands, the heading of the robot, and finally the x and y reference velocities are put into the wheel command mixing matrix, ''Wheel input mixer''. If you are using PIDs you will want to force this heading input to be zero all the time. This block calculate the command that should be sent to each wheel. These wheel commands pass though some saturation and scaling blocks and then are passed into the ''H-bridge model'' MATLAB Function block. This converts the controller output to a command for the motor between -1 and 1. This command is passed into the ''motor'' subsystems. These blocks take in this command the battery voltage and the velocity of the wheel which was summed from the body linear velocities of the cart and yaw velocity. This subsystem uses Simulink blocks to calculate the force produced by each wheel. The calcaultions done in this subsystem can be found in Chapters 3.5 and 3.7 of Paul Uhing's Thesis. ==== System commands ==== The system commands block is fairly strait forward. This subsystem just uses the From_Workspace Simulink blocks, step inputs and other Simulink source blocks to create the input reference commands for the simulation. ==== Body velocity calculations ==== === Modifying Simulink === ==== Creating a new simulation ==== ==== Modifying existing files ==== 760d430a5661e447af900988969a299aff23d394 293 292 2016-08-08T17:59:05Z Pfuhing 5 /* Body velocity calculations */ wikitext text/x-wiki == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] Simulink comes with MATLAB. You should get MATLAB 2014b or latter to ensure the Simulink files from Paul Uhing's research repository will work with your installation of MATLAB. Once the install is complete and MATLAB is registered you can open MATLAB up. Then change the folder MATLAB will work out of to a directory you will want to work form. It would be best to copy a few files from Paul Uhing's repository to help you get started. Inside of the RADA Research Repository go to ''MATLAB/RADA'' and copy ''modelParams_smallWheels_RADA.m'', ''Hbrigeest.mat'', ''Kvw_calc.mat'', ''Hmu_r_erisLargeWheels.mat'', ''LQI_recalc.m'', and ''RADA_ctrlSep.m'' from this directory to you new diectroy as these files will allow you to load the model parameters and controller designs used in Paul Uhing's thesis or find the most recent version of these files an copy them instead. It would also be good to copy and of the ''RADA_psiCtrl_v2.slx'' or ''RADA_psiCtrl_LQGsep.slx'' files here to sever as the base RADA simulation in your new directory. Finally, open te ''DataSets'' directory below the ''RADA'' directory can copy one of the ''RADA_LQG_compPID.mat'' files or ''RADA_LQG_sep.mat'' files because it will allow you to have input vector for the copied ''.slx'' Simulink file. === Setting up the MATLAB Workspace === Now in MATLAB with you working directory set to you new directory for test RADA simulations run ''modelParams_smallWheels_RADA.m'' from the MATLAB command line ten load the RADA ''.mat'' data file. Now in the Current Folder screen in MATLAB double click on the ''.slx'' and wait for it to open. === Settings in Simulink === When running a simulation RADA in simulink always make sure your solver is set to '''ode23t'''! The RADA model is a moderately stiff set of differential equations and ode45 the default solver will take an extremely long time to run simulaitons of RADA. You can set the run length to any length you want and then run the simulation. === Store Data from Simulink === All of the Simulink files in Paul Uhing's Research Repository output simulation data MATLAB structures contain the time and value arrays for important variables. After a simulation finishes these will show up as variables in the MATLAB Workspace. If you want to save any of these values for latter use select them in the MATLAB Workspace and right-click and select save or press ctrl+s to save these variables to a ''.mat'' file. == Understanding and Modifying RADA Simulations == The Simulink models of RADA for Paul Uhing's Thesis is built to be fairly easy to understand. Normal Simulink blocks are used for routing signals and completing simple calculations. For more difficult calculations MATLAB Function blocks are used. These blocks allow you to write MATLAB code to complete some calculation. They can have inputs from the Simulink simulation and parameter inputs from the MATLAB Workspace. This makes complex calculations much easier to understand. The goal of using all of these tricks is to avoid creating a model that is a rat's nest of interconnecting blocks that is impossible trace any errors in the simulation. Understanding how the RADA model was put together wil help you understand how to modify this model and how to build your own models. === Components of the Model === The model is broken down into subsystems based off of sub-components of the actual system. There is a block for calculating the accelerations of RADA's body, two blocks for calculating the different actuator sets, producing commands to the system, and calculating intermediate values used by other blocks. ==== Body dynamics calculations ==== The body dynamics block (''RADA_BodyDynamcis_v2'') takes in Euler angle position and velocity of the pendulum (including yaw), the global velocity of the ground vehicle, the force produced by the propellers in the x body direction of the pendulum, the force produced by the propellers in the y body direction of the pendulum, and the force produced by each wheel. This block is a MATLAB Function block so it also has parameter inputs. For using MATLAB Function block is is important to never delete: %#codegen because this allows the MATLAB code to function in Simulink. The code inside the block is just the implementation of the final equation in Chapter 3.4 of Paul Uhing's Thesis. The outputs of the block are the acceleration of the pendulum's in pitch and roll, the acceleration of the yaw of the system, and the x and y global acceleration of the ground robot. Then MATLAB continuous time integrator blocks are used to get the corresponding velocities and positions. MATLAB function blocks do not do integration very well so it is easier just to calculate the accelerations and then use the Simulink blocks to integrate. == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] Simulink comes with MATLAB. You should get MATLAB 2014b or latter to ensure the Simulink files from Paul Uhing's research repository will work with your installation of MATLAB. Once the install is complete and MATLAB is registered you can open MATLAB up. Then change the folder MATLAB will work out of to a directory you will want to work form. It would be best to copy a few files from Paul Uhing's repository to help you get started. Inside of the RADA Research Repository go to ''MATLAB/RADA'' and copy ''modelParams_smallWheels_RADA.m'', ''Hbrigeest.mat'', ''Kvw_calc.mat'', ''Hmu_r_erisLargeWheels.mat'', ''LQI_recalc.m'', and ''RADA_ctrlSep.m'' from this directory to you new diectroy as these files will allow you to load the model parameters and controller designs used in Paul Uhing's thesis or find the most recent version of these files an copy them instead. It would also be good to copy and of the ''RADA_psiCtrl_v2.slx'' or ''RADA_psiCtrl_LQGsep.slx'' files here to sever as the base RADA simulation in your new directory. Finally, open te ''DataSets'' directory below the ''RADA'' directory can copy one of the ''RADA_LQG_compPID.mat'' files or ''RADA_LQG_sep.mat'' files because it will allow you to have input vector for the copied ''.slx'' Simulink file. === Setting up the MATLAB Workspace === Now in MATLAB with you working directory set to you new directory for test RADA simulations run ''modelParams_smallWheels_RADA.m'' from the MATLAB command line ten load the RADA ''.mat'' data file. Now in the Current Folder screen in MATLAB double click on the ''.slx'' and wait for it to open. === Settings in Simulink === When running a simulation RADA in simulink always make sure your solver is set to '''ode23t'''! The RADA model is a moderately stiff set of differential equations and ode45 the default solver will take an extremely long time to run simulaitons of RADA. You can set the run length to any length you want and then run the simulation. === Store Data from Simulink === All of the Simulink files in Paul Uhing's Research Repository output simulation data MATLAB structures contain the time and value arrays for important variables. After a simulation finishes these will show up as variables in the MATLAB Workspace. If you want to save any of these values for latter use select them in the MATLAB Workspace and right-click and select save or press ctrl+s to save these variables to a ''.mat'' file. == Understanding and Modifying RADA Simulations == The Simulink models of RADA for Paul Uhing's Thesis is built to be fairly easy to understand. Normal Simulink blocks are used for routing signals and completing simple calculations. For more difficult calculations MATLAB Function blocks are used. These blocks allow you to write MATLAB code to complete some calculation. They can have inputs from the Simulink simulation and parameter inputs from the MATLAB Workspace. This makes complex calculations much easier to understand. The goal of using all of these tricks is to avoid creating a model that is a rat's nest of interconnecting blocks that is impossible trace any errors in the simulation. Understanding how the RADA model was put together wil help you understand how to modify this model and how to build your own models. === Components of the Model === The model is broken down into subsystems based off of sub-components of the actual system. There is a block for calculating the accelerations of RADA's body, two blocks for calculating the different actuator sets, producing commands to the system, and calculating intermediate values used by other blocks. ==== Body dynamics calculations ==== The body dynamics block (''RADA_BodyDynamcis_v2'') takes in Euler angle position and velocity of the pendulum (including yaw), the global velocity of the ground vehicle, the force produced by the propellers in the x body direction of the pendulum, the force produced by the propellers in the y body direction of the pendulum, and the force produced by each wheel. This block is a MATLAB Function block so it also has parameter inputs. For using MATLAB Function block is is important to never delete: %#codegen because this allows the MATLAB code to function in Simulink. The code inside the block is just the implementation of the final equation in Chapter 3.4 and 3.5 of Paul Uhing's Thesis. The outputs of the block are the acceleration of the pendulum's in pitch and roll, the acceleration of the yaw of the system, and the x and y global acceleration of the ground robot. Then MATLAB continuous time integrator blocks are used to get the corresponding velocities and positions. MATLAB function blocks do not do integration very well so it is easier just to calculate the accelerations and then use the Simulink blocks to integrate. ==== Actuator dynamics calculations ==== The actuator dynamics in general take in commands from the controller, mix them into individual motor commands and then calculate the force outputs of the motors. There are two actuator dynamics calculation subsystems. One for the propellers and one for the wheels. The controller output is calculated before these blocks and after the input command block. You just put whatever controller you want to use. ===== Propellers ===== The propeller subsystem takes in the the pitch and roll commands, the Euler angle velocities, the cart body velocities and the pitch and roll position. The pitch and roll inputs are mixed into actual motor commands using the ''Pitch_mixer'' and ''Roll_mixer''. These two MATLAB function blocks transform the command into something that can be used by the motor normalized between zero and one. Then the motor command, battery voltage and current motor velocity is passed into the motor MATLAB function blocks. These blocks calculate the acceleration of the propeller motors. That acceleration is integrated and the motor velocity is feedback into the motor block and then sent to the ''motor to force'' block. This MATLAB Function block uses the four propeller velocities, the angular velocities of the pendulum, and the body velocities of the cart. The output of the block is the total force output in the x and y pendulum axis. Finally there is a MATLAB function block, ''localAngleVel'' will calculate convert the global Euler angle velocities to to local body angular velocities. For how the model is generally used this last block isn't necessary but if you are going to have the pendulum do any maneuvers with large angular changes in both pitch and roll using this block will give you better results. The calculations for all of this blocks come from Chapters 2.2, 3.6 and 3.7 of Paul Uhing's Thesis. ===== Wheels ===== The ''WheelForce'' subsystem of the RADA model takes in the heading, x and y controller outputs, the body linear velocities of the cart, the yaw velocity of the cart, the heading of the cart and finally takes in the x and y reference commands. This block then outputs the force produced by each of the four wheels. The heading controller output command, the x and y velocity commands, the heading of the robot, and finally the x and y reference velocities are put into the wheel command mixing matrix, ''Wheel input mixer''. If you are using PIDs you will want to force this heading input to be zero all the time. This block calculate the command that should be sent to each wheel. These wheel commands pass though some saturation and scaling blocks and then are passed into the ''H-bridge model'' MATLAB Function block. This converts the controller output to a command for the motor between -1 and 1. This command is passed into the ''motor'' subsystems. These blocks take in this command the battery voltage and the velocity of the wheel which was summed from the body linear velocities of the cart and yaw velocity. This subsystem uses Simulink blocks to calculate the force produced by each wheel. The calcaultions done in this subsystem can be found in Chapters 3.5 and 3.7 of Paul Uhing's Thesis. ==== System commands ==== The system commands block is fairly strait forward. This subsystem just uses the From_Workspace Simulink blocks, step inputs and other Simulink source blocks to create the input reference commands for the simulation. ==== Body velocity calculations ==== This MATLAB Function block, ''body_vel'' calcuates the body linear velocities of the cart using the heading and global linear velocities of the cart to calculate the body linear velocities of the cart. The equation for this is in Chapter 2.2 of Paul Uhing's Thesis. === Modifying Simulink === ==== Creating a new simulation ==== ==== Modifying existing files ==== bd8d3d2dea229d0bf03024681b118455f03e008a 294 293 2016-08-08T18:43:35Z Pfuhing 5 /* Modifying Simulink */ wikitext text/x-wiki == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] Simulink comes with MATLAB. You should get MATLAB 2014b or latter to ensure the Simulink files from Paul Uhing's research repository will work with your installation of MATLAB. Once the install is complete and MATLAB is registered you can open MATLAB up. Then change the folder MATLAB will work out of to a directory you will want to work form. It would be best to copy a few files from Paul Uhing's repository to help you get started. Inside of the RADA Research Repository go to ''MATLAB/RADA'' and copy ''modelParams_smallWheels_RADA.m'', ''Hbrigeest.mat'', ''Kvw_calc.mat'', ''Hmu_r_erisLargeWheels.mat'', ''LQI_recalc.m'', and ''RADA_ctrlSep.m'' from this directory to you new diectroy as these files will allow you to load the model parameters and controller designs used in Paul Uhing's thesis or find the most recent version of these files an copy them instead. It would also be good to copy and of the ''RADA_psiCtrl_v2.slx'' or ''RADA_psiCtrl_LQGsep.slx'' files here to sever as the base RADA simulation in your new directory. Finally, open te ''DataSets'' directory below the ''RADA'' directory can copy one of the ''RADA_LQG_compPID.mat'' files or ''RADA_LQG_sep.mat'' files because it will allow you to have input vector for the copied ''.slx'' Simulink file. === Setting up the MATLAB Workspace === Now in MATLAB with you working directory set to you new directory for test RADA simulations run ''modelParams_smallWheels_RADA.m'' from the MATLAB command line ten load the RADA ''.mat'' data file. Now in the Current Folder screen in MATLAB double click on the ''.slx'' and wait for it to open. === Settings in Simulink === When running a simulation RADA in simulink always make sure your solver is set to '''ode23t'''! The RADA model is a moderately stiff set of differential equations and ode45 the default solver will take an extremely long time to run simulaitons of RADA. You can set the run length to any length you want and then run the simulation. === Store Data from Simulink === All of the Simulink files in Paul Uhing's Research Repository output simulation data MATLAB structures contain the time and value arrays for important variables. After a simulation finishes these will show up as variables in the MATLAB Workspace. If you want to save any of these values for latter use select them in the MATLAB Workspace and right-click and select save or press ctrl+s to save these variables to a ''.mat'' file. == Understanding and Modifying RADA Simulations == The Simulink models of RADA for Paul Uhing's Thesis is built to be fairly easy to understand. Normal Simulink blocks are used for routing signals and completing simple calculations. For more difficult calculations MATLAB Function blocks are used. These blocks allow you to write MATLAB code to complete some calculation. They can have inputs from the Simulink simulation and parameter inputs from the MATLAB Workspace. This makes complex calculations much easier to understand. The goal of using all of these tricks is to avoid creating a model that is a rat's nest of interconnecting blocks that is impossible trace any errors in the simulation. Understanding how the RADA model was put together wil help you understand how to modify this model and how to build your own models. === Components of the Model === The model is broken down into subsystems based off of sub-components of the actual system. There is a block for calculating the accelerations of RADA's body, two blocks for calculating the different actuator sets, producing commands to the system, and calculating intermediate values used by other blocks. ==== Body dynamics calculations ==== The body dynamics block (''RADA_BodyDynamcis_v2'') takes in Euler angle position and velocity of the pendulum (including yaw), the global velocity of the ground vehicle, the force produced by the propellers in the x body direction of the pendulum, the force produced by the propellers in the y body direction of the pendulum, and the force produced by each wheel. This block is a MATLAB Function block so it also has parameter inputs. For using MATLAB Function block is is important to never delete: %#codegen because this allows the MATLAB code to function in Simulink. The code inside the block is just the implementation of the final equation in Chapter 3.4 of Paul Uhing's Thesis. The outputs of the block are the acceleration of the pendulum's in pitch and roll, the acceleration of the yaw of the system, and the x and y global acceleration of the ground robot. Then MATLAB continuous time integrator blocks are used to get the corresponding velocities and positions. MATLAB function blocks do not do integration very well so it is easier just to calculate the accelerations and then use the Simulink blocks to integrate. == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] Simulink comes with MATLAB. You should get MATLAB 2014b or latter to ensure the Simulink files from Paul Uhing's research repository will work with your installation of MATLAB. Once the install is complete and MATLAB is registered you can open MATLAB up. Then change the folder MATLAB will work out of to a directory you will want to work form. It would be best to copy a few files from Paul Uhing's repository to help you get started. Inside of the RADA Research Repository go to ''MATLAB/RADA'' and copy ''modelParams_smallWheels_RADA.m'', ''Hbrigeest.mat'', ''Kvw_calc.mat'', ''Hmu_r_erisLargeWheels.mat'', ''LQI_recalc.m'', and ''RADA_ctrlSep.m'' from this directory to you new diectroy as these files will allow you to load the model parameters and controller designs used in Paul Uhing's thesis or find the most recent version of these files an copy them instead. It would also be good to copy and of the ''RADA_psiCtrl_v2.slx'' or ''RADA_psiCtrl_LQGsep.slx'' files here to sever as the base RADA simulation in your new directory. Finally, open te ''DataSets'' directory below the ''RADA'' directory can copy one of the ''RADA_LQG_compPID.mat'' files or ''RADA_LQG_sep.mat'' files because it will allow you to have input vector for the copied ''.slx'' Simulink file. === Setting up the MATLAB Workspace === Now in MATLAB with you working directory set to you new directory for test RADA simulations run ''modelParams_smallWheels_RADA.m'' from the MATLAB command line ten load the RADA ''.mat'' data file. Now in the Current Folder screen in MATLAB double click on the ''.slx'' and wait for it to open. === Settings in Simulink === When running a simulation RADA in simulink always make sure your solver is set to '''ode23t'''! The RADA model is a moderately stiff set of differential equations and ode45 the default solver will take an extremely long time to run simulaitons of RADA. You can set the run length to any length you want and then run the simulation. === Store Data from Simulink === All of the Simulink files in Paul Uhing's Research Repository output simulation data MATLAB structures contain the time and value arrays for important variables. After a simulation finishes these will show up as variables in the MATLAB Workspace. If you want to save any of these values for latter use select them in the MATLAB Workspace and right-click and select save or press ctrl+s to save these variables to a ''.mat'' file. == Understanding and Modifying RADA Simulations == The Simulink models of RADA for Paul Uhing's Thesis is built to be fairly easy to understand. Normal Simulink blocks are used for routing signals and completing simple calculations. For more difficult calculations MATLAB Function blocks are used. These blocks allow you to write MATLAB code to complete some calculation. They can have inputs from the Simulink simulation and parameter inputs from the MATLAB Workspace. This makes complex calculations much easier to understand. The goal of using all of these tricks is to avoid creating a model that is a rat's nest of interconnecting blocks that is impossible trace any errors in the simulation. Understanding how the RADA model was put together wil help you understand how to modify this model and how to build your own models. === Components of the Model === The model is broken down into subsystems based off of sub-components of the actual system. There is a block for calculating the accelerations of RADA's body, two blocks for calculating the different actuator sets, producing commands to the system, and calculating intermediate values used by other blocks. ==== Body dynamics calculations ==== The body dynamics block (''RADA_BodyDynamcis_v2'') takes in Euler angle position and velocity of the pendulum (including yaw), the global velocity of the ground vehicle, the force produced by the propellers in the x body direction of the pendulum, the force produced by the propellers in the y body direction of the pendulum, and the force produced by each wheel. This block is a MATLAB Function block so it also has parameter inputs. For using MATLAB Function block is is important to never delete: %#codegen because this allows the MATLAB code to function in Simulink. The code inside the block is just the implementation of the final equation in Chapter 3.4 and 3.5 of Paul Uhing's Thesis. The outputs of the block are the acceleration of the pendulum's in pitch and roll, the acceleration of the yaw of the system, and the x and y global acceleration of the ground robot. Then MATLAB continuous time integrator blocks are used to get the corresponding velocities and positions. MATLAB function blocks do not do integration very well so it is easier just to calculate the accelerations and then use the Simulink blocks to integrate. ==== Actuator dynamics calculations ==== The actuator dynamics in general take in commands from the controller, mix them into individual motor commands and then calculate the force outputs of the motors. There are two actuator dynamics calculation subsystems. One for the propellers and one for the wheels. The controller output is calculated before these blocks and after the input command block. You just put whatever controller you want to use. ===== Propellers ===== The propeller subsystem takes in the the pitch and roll commands, the Euler angle velocities, the cart body velocities and the pitch and roll position. The pitch and roll inputs are mixed into actual motor commands using the ''Pitch_mixer'' and ''Roll_mixer''. These two MATLAB function blocks transform the command into something that can be used by the motor normalized between zero and one. Then the motor command, battery voltage and current motor velocity is passed into the motor MATLAB function blocks. These blocks calculate the acceleration of the propeller motors. That acceleration is integrated and the motor velocity is feedback into the motor block and then sent to the ''motor to force'' block. This MATLAB Function block uses the four propeller velocities, the angular velocities of the pendulum, and the body velocities of the cart. The output of the block is the total force output in the x and y pendulum axis. Finally there is a MATLAB function block, ''localAngleVel'' will calculate convert the global Euler angle velocities to to local body angular velocities. For how the model is generally used this last block isn't necessary but if you are going to have the pendulum do any maneuvers with large angular changes in both pitch and roll using this block will give you better results. The calculations for all of this blocks come from Chapters 2.2, 3.6 and 3.7 of Paul Uhing's Thesis. ===== Wheels ===== The ''WheelForce'' subsystem of the RADA model takes in the heading, x and y controller outputs, the body linear velocities of the cart, the yaw velocity of the cart, the heading of the cart and finally takes in the x and y reference commands. This block then outputs the force produced by each of the four wheels. The heading controller output command, the x and y velocity commands, the heading of the robot, and finally the x and y reference velocities are put into the wheel command mixing matrix, ''Wheel input mixer''. If you are using PIDs you will want to force this heading input to be zero all the time. This block calculate the command that should be sent to each wheel. These wheel commands pass though some saturation and scaling blocks and then are passed into the ''H-bridge model'' MATLAB Function block. This converts the controller output to a command for the motor between -1 and 1. This command is passed into the ''motor'' subsystems. These blocks take in this command the battery voltage and the velocity of the wheel which was summed from the body linear velocities of the cart and yaw velocity. This subsystem uses Simulink blocks to calculate the force produced by each wheel. The calcaultions done in this subsystem can be found in Chapters 3.5 and 3.7 of Paul Uhing's Thesis. ==== System commands ==== The system commands block is fairly strait forward. This subsystem just uses the From_Workspace Simulink blocks, step inputs and other Simulink source blocks to create the input reference commands for the simulation. ==== Body velocity calculations ==== This MATLAB Function block, ''body_vel'' calcuates the body linear velocities of the cart using the heading and global linear velocities of the cart to calculate the body linear velocities of the cart. The equation for this is in Chapter 2.2 of Paul Uhing's Thesis. === Modifying Simulink === When it comes to modifying Simulink there are two options. you can either create a new simulation or modify an existing file. If you are working with the RADA system you should make sure you are using MATLAB 2014b or latter to ensure the Simulink files form Paul Uhing's research will work correctly. Ether way you will need to start MATLAB and set your working directory to the folder that you want to work out of. Then you can open Simulink by opening a Simulink model (file extension ''.xls'' or ''.mdl'') or by typing ''simulink'' into the MATLAB command line. Using the command line will open the Simulink Library window. Either way in newer versions of MATLAB it tends to take Simulink a while to open from MATLAB. ==== Creating a new simulation ==== ==== Modifying existing files ==== c2acd46bd58e60b34be71704e9a04ef8de9c11c7 295 294 2016-08-08T19:08:54Z Pfuhing 5 /* Creating a new simulation */ wikitext text/x-wiki == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] Simulink comes with MATLAB. You should get MATLAB 2014b or latter to ensure the Simulink files from Paul Uhing's research repository will work with your installation of MATLAB. Once the install is complete and MATLAB is registered you can open MATLAB up. Then change the folder MATLAB will work out of to a directory you will want to work form. It would be best to copy a few files from Paul Uhing's repository to help you get started. Inside of the RADA Research Repository go to ''MATLAB/RADA'' and copy ''modelParams_smallWheels_RADA.m'', ''Hbrigeest.mat'', ''Kvw_calc.mat'', ''Hmu_r_erisLargeWheels.mat'', ''LQI_recalc.m'', and ''RADA_ctrlSep.m'' from this directory to you new diectroy as these files will allow you to load the model parameters and controller designs used in Paul Uhing's thesis or find the most recent version of these files an copy them instead. It would also be good to copy and of the ''RADA_psiCtrl_v2.slx'' or ''RADA_psiCtrl_LQGsep.slx'' files here to sever as the base RADA simulation in your new directory. Finally, open te ''DataSets'' directory below the ''RADA'' directory can copy one of the ''RADA_LQG_compPID.mat'' files or ''RADA_LQG_sep.mat'' files because it will allow you to have input vector for the copied ''.slx'' Simulink file. === Setting up the MATLAB Workspace === Now in MATLAB with you working directory set to you new directory for test RADA simulations run ''modelParams_smallWheels_RADA.m'' from the MATLAB command line ten load the RADA ''.mat'' data file. Now in the Current Folder screen in MATLAB double click on the ''.slx'' and wait for it to open. === Settings in Simulink === When running a simulation RADA in simulink always make sure your solver is set to '''ode23t'''! The RADA model is a moderately stiff set of differential equations and ode45 the default solver will take an extremely long time to run simulaitons of RADA. You can set the run length to any length you want and then run the simulation. === Store Data from Simulink === All of the Simulink files in Paul Uhing's Research Repository output simulation data MATLAB structures contain the time and value arrays for important variables. After a simulation finishes these will show up as variables in the MATLAB Workspace. If you want to save any of these values for latter use select them in the MATLAB Workspace and right-click and select save or press ctrl+s to save these variables to a ''.mat'' file. == Understanding and Modifying RADA Simulations == The Simulink models of RADA for Paul Uhing's Thesis is built to be fairly easy to understand. Normal Simulink blocks are used for routing signals and completing simple calculations. For more difficult calculations MATLAB Function blocks are used. These blocks allow you to write MATLAB code to complete some calculation. They can have inputs from the Simulink simulation and parameter inputs from the MATLAB Workspace. This makes complex calculations much easier to understand. The goal of using all of these tricks is to avoid creating a model that is a rat's nest of interconnecting blocks that is impossible trace any errors in the simulation. Understanding how the RADA model was put together wil help you understand how to modify this model and how to build your own models. === Components of the Model === The model is broken down into subsystems based off of sub-components of the actual system. There is a block for calculating the accelerations of RADA's body, two blocks for calculating the different actuator sets, producing commands to the system, and calculating intermediate values used by other blocks. ==== Body dynamics calculations ==== The body dynamics block (''RADA_BodyDynamcis_v2'') takes in Euler angle position and velocity of the pendulum (including yaw), the global velocity of the ground vehicle, the force produced by the propellers in the x body direction of the pendulum, the force produced by the propellers in the y body direction of the pendulum, and the force produced by each wheel. This block is a MATLAB Function block so it also has parameter inputs. For using MATLAB Function block is is important to never delete: %#codegen because this allows the MATLAB code to function in Simulink. The code inside the block is just the implementation of the final equation in Chapter 3.4 of Paul Uhing's Thesis. The outputs of the block are the acceleration of the pendulum's in pitch and roll, the acceleration of the yaw of the system, and the x and y global acceleration of the ground robot. Then MATLAB continuous time integrator blocks are used to get the corresponding velocities and positions. MATLAB function blocks do not do integration very well so it is easier just to calculate the accelerations and then use the Simulink blocks to integrate. == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] Simulink comes with MATLAB. You should get MATLAB 2014b or latter to ensure the Simulink files from Paul Uhing's research repository will work with your installation of MATLAB. Once the install is complete and MATLAB is registered you can open MATLAB up. Then change the folder MATLAB will work out of to a directory you will want to work form. It would be best to copy a few files from Paul Uhing's repository to help you get started. Inside of the RADA Research Repository go to ''MATLAB/RADA'' and copy ''modelParams_smallWheels_RADA.m'', ''Hbrigeest.mat'', ''Kvw_calc.mat'', ''Hmu_r_erisLargeWheels.mat'', ''LQI_recalc.m'', and ''RADA_ctrlSep.m'' from this directory to you new diectroy as these files will allow you to load the model parameters and controller designs used in Paul Uhing's thesis or find the most recent version of these files an copy them instead. It would also be good to copy and of the ''RADA_psiCtrl_v2.slx'' or ''RADA_psiCtrl_LQGsep.slx'' files here to sever as the base RADA simulation in your new directory. Finally, open te ''DataSets'' directory below the ''RADA'' directory can copy one of the ''RADA_LQG_compPID.mat'' files or ''RADA_LQG_sep.mat'' files because it will allow you to have input vector for the copied ''.slx'' Simulink file. === Setting up the MATLAB Workspace === Now in MATLAB with you working directory set to you new directory for test RADA simulations run ''modelParams_smallWheels_RADA.m'' from the MATLAB command line ten load the RADA ''.mat'' data file. Now in the Current Folder screen in MATLAB double click on the ''.slx'' and wait for it to open. === Settings in Simulink === When running a simulation RADA in simulink always make sure your solver is set to '''ode23t'''! The RADA model is a moderately stiff set of differential equations and ode45 the default solver will take an extremely long time to run simulaitons of RADA. You can set the run length to any length you want and then run the simulation. === Store Data from Simulink === All of the Simulink files in Paul Uhing's Research Repository output simulation data MATLAB structures contain the time and value arrays for important variables. After a simulation finishes these will show up as variables in the MATLAB Workspace. If you want to save any of these values for latter use select them in the MATLAB Workspace and right-click and select save or press ctrl+s to save these variables to a ''.mat'' file. == Understanding and Modifying RADA Simulations == The Simulink models of RADA for Paul Uhing's Thesis is built to be fairly easy to understand. Normal Simulink blocks are used for routing signals and completing simple calculations. For more difficult calculations MATLAB Function blocks are used. These blocks allow you to write MATLAB code to complete some calculation. They can have inputs from the Simulink simulation and parameter inputs from the MATLAB Workspace. This makes complex calculations much easier to understand. The goal of using all of these tricks is to avoid creating a model that is a rat's nest of interconnecting blocks that is impossible trace any errors in the simulation. Understanding how the RADA model was put together wil help you understand how to modify this model and how to build your own models. === Components of the Model === The model is broken down into subsystems based off of sub-components of the actual system. There is a block for calculating the accelerations of RADA's body, two blocks for calculating the different actuator sets, producing commands to the system, and calculating intermediate values used by other blocks. ==== Body dynamics calculations ==== The body dynamics block (''RADA_BodyDynamcis_v2'') takes in Euler angle position and velocity of the pendulum (including yaw), the global velocity of the ground vehicle, the force produced by the propellers in the x body direction of the pendulum, the force produced by the propellers in the y body direction of the pendulum, and the force produced by each wheel. This block is a MATLAB Function block so it also has parameter inputs. For using MATLAB Function block is is important to never delete: %#codegen because this allows the MATLAB code to function in Simulink. The code inside the block is just the implementation of the final equation in Chapter 3.4 and 3.5 of Paul Uhing's Thesis. The outputs of the block are the acceleration of the pendulum's in pitch and roll, the acceleration of the yaw of the system, and the x and y global acceleration of the ground robot. Then MATLAB continuous time integrator blocks are used to get the corresponding velocities and positions. MATLAB function blocks do not do integration very well so it is easier just to calculate the accelerations and then use the Simulink blocks to integrate. ==== Actuator dynamics calculations ==== The actuator dynamics in general take in commands from the controller, mix them into individual motor commands and then calculate the force outputs of the motors. There are two actuator dynamics calculation subsystems. One for the propellers and one for the wheels. The controller output is calculated before these blocks and after the input command block. You just put whatever controller you want to use. ===== Propellers ===== The propeller subsystem takes in the the pitch and roll commands, the Euler angle velocities, the cart body velocities and the pitch and roll position. The pitch and roll inputs are mixed into actual motor commands using the ''Pitch_mixer'' and ''Roll_mixer''. These two MATLAB function blocks transform the command into something that can be used by the motor normalized between zero and one. Then the motor command, battery voltage and current motor velocity is passed into the motor MATLAB function blocks. These blocks calculate the acceleration of the propeller motors. That acceleration is integrated and the motor velocity is feedback into the motor block and then sent to the ''motor to force'' block. This MATLAB Function block uses the four propeller velocities, the angular velocities of the pendulum, and the body velocities of the cart. The output of the block is the total force output in the x and y pendulum axis. Finally there is a MATLAB function block, ''localAngleVel'' will calculate convert the global Euler angle velocities to to local body angular velocities. For how the model is generally used this last block isn't necessary but if you are going to have the pendulum do any maneuvers with large angular changes in both pitch and roll using this block will give you better results. The calculations for all of this blocks come from Chapters 2.2, 3.6 and 3.7 of Paul Uhing's Thesis. ===== Wheels ===== The ''WheelForce'' subsystem of the RADA model takes in the heading, x and y controller outputs, the body linear velocities of the cart, the yaw velocity of the cart, the heading of the cart and finally takes in the x and y reference commands. This block then outputs the force produced by each of the four wheels. The heading controller output command, the x and y velocity commands, the heading of the robot, and finally the x and y reference velocities are put into the wheel command mixing matrix, ''Wheel input mixer''. If you are using PIDs you will want to force this heading input to be zero all the time. This block calculate the command that should be sent to each wheel. These wheel commands pass though some saturation and scaling blocks and then are passed into the ''H-bridge model'' MATLAB Function block. This converts the controller output to a command for the motor between -1 and 1. This command is passed into the ''motor'' subsystems. These blocks take in this command the battery voltage and the velocity of the wheel which was summed from the body linear velocities of the cart and yaw velocity. This subsystem uses Simulink blocks to calculate the force produced by each wheel. The calcaultions done in this subsystem can be found in Chapters 3.5 and 3.7 of Paul Uhing's Thesis. ==== System commands ==== The system commands block is fairly strait forward. This subsystem just uses the From_Workspace Simulink blocks, step inputs and other Simulink source blocks to create the input reference commands for the simulation. ==== Body velocity calculations ==== This MATLAB Function block, ''body_vel'' calcuates the body linear velocities of the cart using the heading and global linear velocities of the cart to calculate the body linear velocities of the cart. The equation for this is in Chapter 2.2 of Paul Uhing's Thesis. === Modifying Simulink === When it comes to modifying Simulink there are two options. you can either create a new simulation or modify an existing file. If you are working with the RADA system you should make sure you are using MATLAB 2014b or latter to ensure the Simulink files form Paul Uhing's research will work correctly. Ether way you will need to start MATLAB and set your working directory to the folder that you want to work out of. Then you can open Simulink by opening a Simulink model (file extension ''.xls'' or ''.mdl'') or by typing ''simulink'' into the MATLAB command line. Using the command line will open the Simulink Library window. Either way in newer versions of MATLAB it tends to take Simulink a while to open from MATLAB. ==== Creating a new simulation ==== To create a new Simulink model either in an existing model ''File->New->Model'' or you can click on the new model button. You can also use the new model button in the Simulink Library window. Now a new model page will open up. The first thing you will want to do if you are going to use the model for RADA is to change the ordinary differential equations (ODE) solver. In Simulink the ODE solver will default to the continuous time solver ''ode45'' but this solver doesn't work well for stiff differential equations. Because RADA is a moderately stiff system you will want to change the solver to the continuous time ODE solver ''ode23t''. Do this by going to ''Simulation->Model Configuration Parameters'' or press ''ctrl+E''. This opens up the model parameters panel. Here you have all the same options you would if you were using the ODE solver in MATLAB. In the solver drop down menu choose ''ode23t'' and then click ''Apply'' or ''OK''. Now you can build the model however you want or copy in systems from other models. ==== Modifying existing files ==== 9a8ab20c1004bbdd62541bbeb457474ddb5a15b8 296 295 2016-08-08T19:18:09Z Pfuhing 5 /* Modifying existing files */ wikitext text/x-wiki == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] Simulink comes with MATLAB. You should get MATLAB 2014b or latter to ensure the Simulink files from Paul Uhing's research repository will work with your installation of MATLAB. Once the install is complete and MATLAB is registered you can open MATLAB up. Then change the folder MATLAB will work out of to a directory you will want to work form. It would be best to copy a few files from Paul Uhing's repository to help you get started. Inside of the RADA Research Repository go to ''MATLAB/RADA'' and copy ''modelParams_smallWheels_RADA.m'', ''Hbrigeest.mat'', ''Kvw_calc.mat'', ''Hmu_r_erisLargeWheels.mat'', ''LQI_recalc.m'', and ''RADA_ctrlSep.m'' from this directory to you new diectroy as these files will allow you to load the model parameters and controller designs used in Paul Uhing's thesis or find the most recent version of these files an copy them instead. It would also be good to copy and of the ''RADA_psiCtrl_v2.slx'' or ''RADA_psiCtrl_LQGsep.slx'' files here to sever as the base RADA simulation in your new directory. Finally, open te ''DataSets'' directory below the ''RADA'' directory can copy one of the ''RADA_LQG_compPID.mat'' files or ''RADA_LQG_sep.mat'' files because it will allow you to have input vector for the copied ''.slx'' Simulink file. === Setting up the MATLAB Workspace === Now in MATLAB with you working directory set to you new directory for test RADA simulations run ''modelParams_smallWheels_RADA.m'' from the MATLAB command line ten load the RADA ''.mat'' data file. Now in the Current Folder screen in MATLAB double click on the ''.slx'' and wait for it to open. === Settings in Simulink === When running a simulation RADA in simulink always make sure your solver is set to '''ode23t'''! The RADA model is a moderately stiff set of differential equations and ode45 the default solver will take an extremely long time to run simulaitons of RADA. You can set the run length to any length you want and then run the simulation. === Store Data from Simulink === All of the Simulink files in Paul Uhing's Research Repository output simulation data MATLAB structures contain the time and value arrays for important variables. After a simulation finishes these will show up as variables in the MATLAB Workspace. If you want to save any of these values for latter use select them in the MATLAB Workspace and right-click and select save or press ctrl+s to save these variables to a ''.mat'' file. == Understanding and Modifying RADA Simulations == The Simulink models of RADA for Paul Uhing's Thesis is built to be fairly easy to understand. Normal Simulink blocks are used for routing signals and completing simple calculations. For more difficult calculations MATLAB Function blocks are used. These blocks allow you to write MATLAB code to complete some calculation. They can have inputs from the Simulink simulation and parameter inputs from the MATLAB Workspace. This makes complex calculations much easier to understand. The goal of using all of these tricks is to avoid creating a model that is a rat's nest of interconnecting blocks that is impossible trace any errors in the simulation. Understanding how the RADA model was put together wil help you understand how to modify this model and how to build your own models. === Components of the Model === The model is broken down into subsystems based off of sub-components of the actual system. There is a block for calculating the accelerations of RADA's body, two blocks for calculating the different actuator sets, producing commands to the system, and calculating intermediate values used by other blocks. ==== Body dynamics calculations ==== The body dynamics block (''RADA_BodyDynamcis_v2'') takes in Euler angle position and velocity of the pendulum (including yaw), the global velocity of the ground vehicle, the force produced by the propellers in the x body direction of the pendulum, the force produced by the propellers in the y body direction of the pendulum, and the force produced by each wheel. This block is a MATLAB Function block so it also has parameter inputs. For using MATLAB Function block is is important to never delete: %#codegen because this allows the MATLAB code to function in Simulink. The code inside the block is just the implementation of the final equation in Chapter 3.4 of Paul Uhing's Thesis. The outputs of the block are the acceleration of the pendulum's in pitch and roll, the acceleration of the yaw of the system, and the x and y global acceleration of the ground robot. Then MATLAB continuous time integrator blocks are used to get the corresponding velocities and positions. MATLAB function blocks do not do integration very well so it is easier just to calculate the accelerations and then use the Simulink blocks to integrate. == Simulink Setup == In order to use Simulink effectively you need to setup a few things. Iowa State will allow you download MATLAB and use a site license for free as a student. For more information about installing MATLAB using this site license look [http://it.engineering.iastate.edu/how-to/installing-matlab/ here.] Simulink comes with MATLAB. You should get MATLAB 2014b or latter to ensure the Simulink files from Paul Uhing's research repository will work with your installation of MATLAB. Once the install is complete and MATLAB is registered you can open MATLAB up. Then change the folder MATLAB will work out of to a directory you will want to work form. It would be best to copy a few files from Paul Uhing's repository to help you get started. Inside of the RADA Research Repository go to ''MATLAB/RADA'' and copy ''modelParams_smallWheels_RADA.m'', ''Hbrigeest.mat'', ''Kvw_calc.mat'', ''Hmu_r_erisLargeWheels.mat'', ''LQI_recalc.m'', and ''RADA_ctrlSep.m'' from this directory to you new diectroy as these files will allow you to load the model parameters and controller designs used in Paul Uhing's thesis or find the most recent version of these files an copy them instead. It would also be good to copy and of the ''RADA_psiCtrl_v2.slx'' or ''RADA_psiCtrl_LQGsep.slx'' files here to sever as the base RADA simulation in your new directory. Finally, open te ''DataSets'' directory below the ''RADA'' directory can copy one of the ''RADA_LQG_compPID.mat'' files or ''RADA_LQG_sep.mat'' files because it will allow you to have input vector for the copied ''.slx'' Simulink file. === Setting up the MATLAB Workspace === Now in MATLAB with you working directory set to you new directory for test RADA simulations run ''modelParams_smallWheels_RADA.m'' from the MATLAB command line ten load the RADA ''.mat'' data file. Now in the Current Folder screen in MATLAB double click on the ''.slx'' and wait for it to open. === Settings in Simulink === When running a simulation RADA in simulink always make sure your solver is set to '''ode23t'''! The RADA model is a moderately stiff set of differential equations and ode45 the default solver will take an extremely long time to run simulaitons of RADA. You can set the run length to any length you want and then run the simulation. === Store Data from Simulink === All of the Simulink files in Paul Uhing's Research Repository output simulation data MATLAB structures contain the time and value arrays for important variables. After a simulation finishes these will show up as variables in the MATLAB Workspace. If you want to save any of these values for latter use select them in the MATLAB Workspace and right-click and select save or press ctrl+s to save these variables to a ''.mat'' file. == Understanding and Modifying RADA Simulations == The Simulink models of RADA for Paul Uhing's Thesis is built to be fairly easy to understand. Normal Simulink blocks are used for routing signals and completing simple calculations. For more difficult calculations MATLAB Function blocks are used. These blocks allow you to write MATLAB code to complete some calculation. They can have inputs from the Simulink simulation and parameter inputs from the MATLAB Workspace. This makes complex calculations much easier to understand. The goal of using all of these tricks is to avoid creating a model that is a rat's nest of interconnecting blocks that is impossible trace any errors in the simulation. Understanding how the RADA model was put together wil help you understand how to modify this model and how to build your own models. === Components of the Model === The model is broken down into subsystems based off of sub-components of the actual system. There is a block for calculating the accelerations of RADA's body, two blocks for calculating the different actuator sets, producing commands to the system, and calculating intermediate values used by other blocks. ==== Body dynamics calculations ==== The body dynamics block (''RADA_BodyDynamcis_v2'') takes in Euler angle position and velocity of the pendulum (including yaw), the global velocity of the ground vehicle, the force produced by the propellers in the x body direction of the pendulum, the force produced by the propellers in the y body direction of the pendulum, and the force produced by each wheel. This block is a MATLAB Function block so it also has parameter inputs. For using MATLAB Function block is is important to never delete: %#codegen because this allows the MATLAB code to function in Simulink. The code inside the block is just the implementation of the final equation in Chapter 3.4 and 3.5 of Paul Uhing's Thesis. The outputs of the block are the acceleration of the pendulum's in pitch and roll, the acceleration of the yaw of the system, and the x and y global acceleration of the ground robot. Then MATLAB continuous time integrator blocks are used to get the corresponding velocities and positions. MATLAB function blocks do not do integration very well so it is easier just to calculate the accelerations and then use the Simulink blocks to integrate. ==== Actuator dynamics calculations ==== The actuator dynamics in general take in commands from the controller, mix them into individual motor commands and then calculate the force outputs of the motors. There are two actuator dynamics calculation subsystems. One for the propellers and one for the wheels. The controller output is calculated before these blocks and after the input command block. You just put whatever controller you want to use. ===== Propellers ===== The propeller subsystem takes in the the pitch and roll commands, the Euler angle velocities, the cart body velocities and the pitch and roll position. The pitch and roll inputs are mixed into actual motor commands using the ''Pitch_mixer'' and ''Roll_mixer''. These two MATLAB function blocks transform the command into something that can be used by the motor normalized between zero and one. Then the motor command, battery voltage and current motor velocity is passed into the motor MATLAB function blocks. These blocks calculate the acceleration of the propeller motors. That acceleration is integrated and the motor velocity is feedback into the motor block and then sent to the ''motor to force'' block. This MATLAB Function block uses the four propeller velocities, the angular velocities of the pendulum, and the body velocities of the cart. The output of the block is the total force output in the x and y pendulum axis. Finally there is a MATLAB function block, ''localAngleVel'' will calculate convert the global Euler angle velocities to to local body angular velocities. For how the model is generally used this last block isn't necessary but if you are going to have the pendulum do any maneuvers with large angular changes in both pitch and roll using this block will give you better results. The calculations for all of this blocks come from Chapters 2.2, 3.6 and 3.7 of Paul Uhing's Thesis. ===== Wheels ===== The ''WheelForce'' subsystem of the RADA model takes in the heading, x and y controller outputs, the body linear velocities of the cart, the yaw velocity of the cart, the heading of the cart and finally takes in the x and y reference commands. This block then outputs the force produced by each of the four wheels. The heading controller output command, the x and y velocity commands, the heading of the robot, and finally the x and y reference velocities are put into the wheel command mixing matrix, ''Wheel input mixer''. If you are using PIDs you will want to force this heading input to be zero all the time. This block calculate the command that should be sent to each wheel. These wheel commands pass though some saturation and scaling blocks and then are passed into the ''H-bridge model'' MATLAB Function block. This converts the controller output to a command for the motor between -1 and 1. This command is passed into the ''motor'' subsystems. These blocks take in this command the battery voltage and the velocity of the wheel which was summed from the body linear velocities of the cart and yaw velocity. This subsystem uses Simulink blocks to calculate the force produced by each wheel. The calcaultions done in this subsystem can be found in Chapters 3.5 and 3.7 of Paul Uhing's Thesis. ==== System commands ==== The system commands block is fairly strait forward. This subsystem just uses the From_Workspace Simulink blocks, step inputs and other Simulink source blocks to create the input reference commands for the simulation. ==== Body velocity calculations ==== This MATLAB Function block, ''body_vel'' calcuates the body linear velocities of the cart using the heading and global linear velocities of the cart to calculate the body linear velocities of the cart. The equation for this is in Chapter 2.2 of Paul Uhing's Thesis. === Modifying Simulink === When it comes to modifying Simulink there are two options. you can either create a new simulation or modify an existing file. If you are working with the RADA system you should make sure you are using MATLAB 2014b or latter to ensure the Simulink files form Paul Uhing's research will work correctly. Ether way you will need to start MATLAB and set your working directory to the folder that you want to work out of. Then you can open Simulink by opening a Simulink model (file extension ''.xls'' or ''.mdl'') or by typing ''simulink'' into the MATLAB command line. Using the command line will open the Simulink Library window. Either way in newer versions of MATLAB it tends to take Simulink a while to open from MATLAB. ==== Creating a new simulation ==== To create a new Simulink model either in an existing model ''File->New->Model'' or you can click on the new model button. You can also use the new model button in the Simulink Library window. Now a new model page will open up. The first thing you will want to do if you are going to use the model for RADA is to change the ordinary differential equations (ODE) solver. In Simulink the ODE solver will default to the continuous time solver ''ode45'' but this solver doesn't work well for stiff differential equations. Because RADA is a moderately stiff system you will want to change the solver to the continuous time ODE solver ''ode23t''. Do this by going to ''Simulation->Model Configuration Parameters'' or press ''ctrl+E''. This opens up the model parameters panel. Here you have all the same options you would if you were using the ODE solver in MATLAB. In the solver drop down menu choose ''ode23t'' and then click ''Apply'' or ''OK''. Now you can build the model however you want or copy in systems from other models. ==== Modifying existing files ==== You can simply open the Simulink file you want to modify. If you are going to make a large number of modifications or delete a lot of things it would be wise to save this model as a new file and modify the new file so you have a backup incase the modified model has problems. This will make debugging much easier. When you do this just make sure the ODE solver is ''ode23t'' as it may default back to ''ode45''. If you are just making small modifications you can just modify the same file. b12da5e4555e438a3dc2bea91d9503aad299497b Using Robotic Agriculture Data Acquisition (RADA) for Research Use 0 48 278 172 2016-08-04T18:54:16Z Pfuhing 5 wikitext text/x-wiki This page discusses the RADA platform for research used. If you want information about the RADA platform see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Main_Page RADA Senior Design Project]. This page will discuss two important issues for using the RADA platform for research: *[[Data Collection and Simulation Comparison]] *[[Setting up and Modifying RADA Simulations]] *[[Test]] The page on data collection and simulation comparison will discus how to set a test of RADA and then take the logged data and compare it to a simulation of RADA in Simulink using the model developed for Paul Uhing's thesis. While the page on setting up and modifing RADA simulations will discuss how RADA Simulink simulations are currently structured and other important information for creating your own Simulink simulations of RADA. 209bd19c78a69a26d705b28a728829f757b6052e 283 278 2016-08-04T19:35:26Z Pfuhing 5 wikitext text/x-wiki This page discusses the RADA platform for research used. If you want information about the RADA platform see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Main_Page RADA Senior Design Project]. This page will discuss two important issues for using the RADA platform for research: *[[Data Collection and Simulation Comparison]] *[[Setting up and Modifying RADA Simulations]] The page on data collection and simulation comparison will discus how to set a test of RADA and then take the logged data and compare it to a simulation of RADA in Simulink using the model developed for Paul Uhing's thesis. While the page on setting up and modifing RADA simulations will discuss how RADA Simulink simulations are currently structured and other important information for creating your own Simulink simulations of RADA. 086138a5c9ed2365ec2d4a88a5cb83a0f9f45b47 Test 0 82 279 2016-08-04T19:23:55Z Pfuhing 5 New page: test wikitext text/x-wiki test a94a8fe5ccb19ba61c4c0873d391e987982fbbd3 280 279 2016-08-04T19:30:24Z Pfuhing 5 wikitext text/x-wiki <div id="top" class="navigation"> <div class="tabs"> <ul> <li>[[index.html|<span>Main Page</span>]]</li> <li>[[annotated.html|<span>Classes</span>]]</li> <li>[[files.html|<span>Files</span>]]</li> ----- Generated on 28 Jul 2016 for RADA Reserarch Code Base by  [http://www.doxygen.org/index.html [[File:doxygen.png|class=footer|doxygen]]] 1.6.1 95f6c53612c9664581c7bc8fb23b4df582707ab1 281 280 2016-08-04T19:32:23Z Pfuhing 5 wikitext text/x-wiki <span>RADA Reserarch Code Base </span><br /> <br /> <br /> = Class Index = == Class List == Here are the classes, structs, unions and interfaces with brief descriptions: = File Index = == File List == Here is a list of all files with brief descriptions: = Class Documentation = <span>#include <math><</math>motor_controller_common.h<math>></math></span> === Public Attributes === double STATES_C double STATES_C double STATES_CSTATES_C double STATES_CINPUTS_C double OUTPUTS_CSTATES_C double OUTPUTS_CINPUTS_C double OUTPUTS_C double INPUTS_C double double double double double double double === Member Data Documentation === [structCTRLSS_a99323b1af830e7170af3eb72aa41d8b3] [structCTRLSS_a751b08ff03f811cd299a275d64a1776a] [structCTRLSS_a3ea95aceed6524af85a73066285a25bd] [structCTRLSS_a01a7190f80d6033577efa0caf702a9de] [structCTRLSS_a3ddf713d4d6a47c452bb2c4f36601720] [structCTRLSS_acc76fcf689629f6d35cb37ef7274421d] [structCTRLSS_a029e4fe6ce170bcb874a0514af186198] [structCTRLSS_a6ce9144e59b5a087b8014e1f58df8292] [structCTRLSS_aea6bc624a0ebf341819b39020909dd04] [structCTRLSS_aab84633e6cc98bb274a137e0dbe0632e] [structCTRLSS_ad0c4dfb12c67eb1eebbe9ecb33ea81c7] [structCTRLSS_a2d457a9fd6b55eb5a445c2dc98ddd7d4] [structCTRLSS_a014cd2f9819f50a41b6a0e685f99be06] [structCTRLSS_a1dd57a341230062f91ffde1ac18f75d4] [structCTRLSS_ad22a1976dcc9969f365d01e0ef0a617e] The documentation for this struct was generated from the following file: <span>#include <math><</math>motor_controller_common.h<math>></math></span> === Public Attributes === double STATES_C_LOSS double STATES_C_LOSS double OUTPUTS_C_LOSS double INPUT2_C_LOSS double OUT1_C_LOSS double INPUT2_C_LOSS double INPUTS_C_LOSS double OUT1_C_LOSS double double double double double double double === Member Data Documentation === [structCTRLSS__loss_a904658b1581cfaf90efcef9cf0f5d48c] [structCTRLSS__loss_ac523ba7a0ee64b1618fdf9346e25bbd0] [structCTRLSS__loss_aad426c6e52a67fc40855671347b0872c] [structCTRLSS__loss_af3504df76d7647c9557e0382cdd5af03] [structCTRLSS__loss_ad9c1f4d4229875c7a8757134e3262f1a] [structCTRLSS__loss_a3306c7c3457a90cfd8913969acd07489] [structCTRLSS__loss_ab6a6d80b9d3bf0609025c2773a03aa6a] [structCTRLSS__loss_a94b30d3d55be796a780f1b7f6ff5d4fd] [structCTRLSS__loss_acfcc19f41c9e4d6ad41763780df431fe] [structCTRLSS__loss_a68ad7dacfd6564154b0ababc73adadb8] [structCTRLSS__loss_a2477cdabb56e7b05643566b0bf54a681] [structCTRLSS__loss_aec54a6d6e7de19b0025d9b5ba71302e8] [structCTRLSS__loss_a2241843bf580dae1221eca4bc7391094] [structCTRLSS__loss_a522a79b355319b1d7f76787ee267d049] [structCTRLSS__loss_a65d0a6c66bb0149fade8a9253cde83af] The documentation for this struct was generated from the following file: <span>#include <math><</math>motor_controller_common.h<math>></math></span> === Public Attributes === double double double double double double float float float float float float float float float float float float float float float float float float float short long float short long float short long float short long float int int struct struct === Member Data Documentation === [structERIS_a594f58e4b65b38fdaab0f83bb7bc8293] [structERIS_affb5711d1d76fd40c46d868b5f6927aa] [structERIS_ad945a9871aa3ed47039939d88f9b2299] [structERIS_a4c8be3873d1d6d36d2adebb5583691fb] [structERIS_a112c7b15e1c3b9e357f7efd450311e8c] [structERIS_a85a4abeca56252fabbf184cb3322a7d6] [structERIS_a9928bd6601057058bc98f0f1eb872292] [structERIS_a869ad31293ee6b745995e7ffe1e6a0f3] [structERIS_ad9b624848a4ec324a96976aa405b045b] [structERIS_a7be16859eb75730aaf5ea03730eeff89] [structERIS_a9fb27e63c72b45f039b459c121057750] [structERIS_a9d0eab06fbf935d7ce8a07ec9f6abda8] [structERIS_a455b48179fcb3643a44977f21ef2bf92] [structERIS_a9d884151e04cd0868cb6bb12cec77add] [structERIS_aaefa4f638c81e80f8b0cfb61a9730566] [structERIS_a63236f07dd96e08e0771f229d100eeeb] [structERIS_aef28562d61240755434169358ea97368] [structERIS_afec79f417cb04b2dcfb9c56a63736014] [structERIS_ae418f284e890ee3c7e0c15df949395c2] [structERIS_ab5d12b6188aa05281c30d1c13d618f4b] [structERIS_a92dc86b172980adc160aeb94a7e27f8d] [structERIS_ad87f4be8f56b23c4e94c5d65c5db2384] [structERIS_a28f58b5c3dd3b40b010ac65650e5eeeb] [structERIS_a04871634308c93a163323a16bbb3b874] [structERIS_a2605317a4567b84182bd96e85af624b5] [structERIS_aa4385dd53171d645bc011c84b5087244] [structERIS_ac372ad4cb17b18d0d3e2ce7bfe970fbc] [structERIS_aa2b057d6e96bd5f4ac3761d9e38689e6] [structERIS_af0200895dba3547c9ea882142cde9197] [structERIS_a816bef39acccbe0732a634827f00091d] [structERIS_a5a7dde7e5ee1b5e68dac70b3a09be745] [structERIS_a15b49effc03c39587df29a16b694242d] [structERIS_a781bf4cc6d4a8af62c7a391c16880979] [structERIS_a1e1caaacbead60ba2bdea30dff17e941] [structERIS_a9cbd69c7ad62832ffd8dcbe255f83d1d] [structERIS_ad0b4447c7045d936f229aee0941c359b] [structERIS_a6c5dbc5227880cb78f6e65c16060f4cb] [structERIS_a5e2e564b7b9cedf1072eafb786890a02] [structERIS_a7ec6d729be463c37f202f6e7a432cbac] [structERIS_a92b52d91f51bf4f211261dc41febaa37] [structERIS_aa56379b46025b8686dd12c0bd8b7145e] [structERIS_a33574ef5cfbce10c10eb83989c176e5f] [structERIS_a52a15839c5ff34a1ddb55730850e93e1] [structERIS_a304ff39c8ab4196a475377baf82f932f] The documentation for this struct was generated from the following file: <span>#include <math><</math>motor_controller_common.h<math>></math></span> === Public Attributes === double 7 double 7 double 6 double 3 double double double === Member Data Documentation === [structERIS__LQG_a8806d631415884c9d64f2d3e518dddde] [structERIS__LQG_ac21c150b49c2fff2adfb0e5057fcc2ab] [structERIS__LQG_a498c5ca3fc85ce54403bef61cf41c875] [structERIS__LQG_a4d7694c9811f751f00f26e4fe43a9cbe] [structERIS__LQG_af6e2db69256e4c6d1502a14e21cb835e] [structERIS__LQG_ac137a0205e4f5816eb7b03d860199165] [structERIS__LQG_ad13d5c23aeb1a3c23b186db27724ef3c] The documentation for this struct was generated from the following file: <span>#include <math><</math>motor_controller_common.h<math>></math></span> === Public Attributes === float float float float float === Member Data Documentation === [structfilter_a09a899b4383ada744678070d267949fb] [structfilter_a1b76e61c6be0159b055e6e653d12e464] [structfilter_aab2e9732f6e1fd3a570996479328a124] [structfilter_ae0db9676750bedeb2e90d845a6e7ebfe] [structfilter_ae9cc7c8691d84414aaf60252fe5a52ec] The documentation for this struct was generated from the following file: <span>#include <math><</math>key_bindings.h<math>></math></span> === Static Public Attributes === static const char = ’v’ static const char = ’b’ static const char = ’n’ static const char = ’2’ static const char = ’m’ static const char = 27 static const char = ’w’ static const char = ’s’ static const char = ’d’ static const char = ’a’ static const char = ’p’ static const char = ’y’ static const char = ’t’ static const char = ’i’ static const char = ’u’ static const char = ’e’ static const char = ’q’ static const char = ’7’ static const char = ’4’ static const char = ’8’ static const char = ’5’ static const char = ’7’ static const char = ’4’ static const char = ’8’ static const char = ’5’ static const char = ’9’ static const char = ’6’ static const char = ’i’ static const char = ’k’ static const char = ’o’ static const char = ’l’ static const char = ’1’ static const char = ’3’ === Member Data Documentation === [classKeyBindings_aef90171b20d79ebc257f170181eaf890] [classKeyBindings_a58695bbfce90d6ffc0a84196d89b9960] [classKeyBindings_af826ec5e2054b40f1deb054e64ca0529] [classKeyBindings_a47c5ee2c44867d20c24f762d36e97f59] [classKeyBindings_aebaae84b4f4db7abdae29caaea528e8b] [classKeyBindings_a06d10f62d58db35f26c4e29f3465f657] [classKeyBindings_a5fd4a7111057bea6e2aa3514ca7e49d4] [classKeyBindings_aa221252e7c8c7dfbd6bf52cec6ff9efa] [classKeyBindings_a3536a06efd932f9f83c7b1401e62ac74] [classKeyBindings_a528caa743573e714305d2f326cdae482] [classKeyBindings_a0601b0f2f1c994b385ef9ff19b445541] [classKeyBindings_a3c4bb88bba2ea8f911fee2ec3e94b621] [classKeyBindings_a65d61f86eb4cce6c226c3a6d5040a5ce] [classKeyBindings_a94d0f20713e0122528f111ac6384a10a] [classKeyBindings_a6a8577243dd58679a919601817459a3d] [classKeyBindings_ac2ab34fa8f84c3e61dd691c85d4d6a9d] [classKeyBindings_ab5de5431af2bbec9beed76240b8e7210] [classKeyBindings_a2bde3f4c440aed4f1ec8004554c8bb6e] [classKeyBindings_a9406856a5b5bb0e59b65d9389abe1229] [classKeyBindings_a83941cf8641d93aa0792519298ea0119] [classKeyBindings_af5a66599d1eb2a203db566ce95f6d667] [classKeyBindings_a0f328dc9694c01262ca88aeaedcbe365] [classKeyBindings_a068e0ae5f38a66b981aa94f6f36db7b5] [classKeyBindings_a947cefad7da0002ef80f31c1bab4e25e] [classKeyBindings_af237d7d82eacdf495b9b9df6d7d1c19d] [classKeyBindings_aedde92ca55442a92af50c0732697cf8f] [classKeyBindings_adf03756ecc709d0f5b73f3b6e162bbda] [classKeyBindings_a126181719b0381e792f0aa3886654698] [classKeyBindings_ab98a06f6baa445e56e6b662adf2f5e54] [classKeyBindings_a118fbfad6a18c2b32204277077f77f67] [classKeyBindings_acff79176396fc2c9c65713c08d0cb36f] [classKeyBindings_a13ccf108959855740a39ee977984b09c] [classKeyBindings_a2cbbf6deb2943cff3496b6da55752c71] The documentation for this class was generated from the following file: <span>#include <math><</math>logger.h<math>></math></span> === Public Member Functions === <span>'''Logger Object Removal'''</span> ''[_amgrpef40c65612bb88d1b1d4e0d91e727cc2] Deleets logger object.'' Removes the logger object by freeing the resouces used by the object. () <span>'''Initialize Logger'''</span> ''[_amgrp3996112c3a768bbd5ae89716a6094e6a] Initialize te logger instance.'' Initializes the data logging by creating the log files. This is called during initialization. <span>Returns</span> true if the log file s open false if the log file is closed bool () === Static Public Member Functions === <span>'''Logger Instance'''</span> ''[_amgrp90163ef8e72e8956084b6b4bd9b35af6] Gets the logger instance.'' Gets the singleton logger obect <span>Returns</span> The logger object static <math>\ast</math> () === Private Member Functions === <span>'''Logger Object'''</span> ''[_amgrp79673e6bbe5de34f023f632dc03e3db4] Creates logger object.'' Creates a default object. It is private to prevent someone from destroying the current instance. () <span>'''Write Logger Header'''</span> ''[_amgrped625226a046a655e3d77605a871ab56] Writes the headder of the log data.'' Writes the pid constants to the top of the log file. Writes the column titles and units to the top of the log file. void () === Static Private Attributes === static <math>\ast</math> = 0 === Stop Logging === Closes the log file. Closes the log file. std::fstream bool bool bool bool bool bool bool bool bool bool <math>\ast</math> <math>\ast</math> <math>\ast</math> void () void () === Constructor &amp; Destructor Documentation === [classLogger_abc41bfb031d896170c7675fa96a6b30c] [classLogger_acb668a9e186a25fbaad2e4af6d1ed00a] === Member Function Documentation === [classLogger_a1287de14553cab2d7fddb74a015cef63] [classLogger_a4a2c28f7530b31a50684bee08c30c30e] [classLogger_a05311a9baf7b23ac45f0fa1a6ce1bea2] Writes a line to the log file. This is called whenever we need to log something into the file [classLogger_a52afa60704b98d0b206fd8bc978d2b0e] [classLogger_a680ecd9a68a45c4203a7b0c03f45e74f] === Member Data Documentation === [classLogger_a3477ad7e31f05db92807692445a2670d] [classLogger_a0fbc31b87c926c9ecf885b0f1675b1fe] [classLogger_ab18889d6fdbe2e2df34fc5f1f9c8bb02] [classLogger_a1f27181977abeeaebe319e1b18fe4b6a] [classLogger_acaa5b8f112473512838b557124e199c9] [classLogger_a9cef2ee3fe1f8c107ad07399ab4dff4a] [classLogger_af7d961fb7fb4b33bf589133ce84261f0] [classLogger_af8be280252ca544b1c2456084ce734aa] [classLogger_ad33727570915401a4960afcb4fcc0116] [classLogger_a06cf172509e2448b2a2c03fd9a20cd0d] [classLogger_ae133c211974fcb334209f997e770d56d] [classLogger_a0fcdcc99336a9fd24fc5d24039ef5393] [classLogger_a88d258aef340bd59cc36b66ab392b420] [classLogger_ad61e110daff94c8c3d5d2c94afbc7322] [classLogger_a3537680ba9f19fe19e98193a60014406] The documentation for this class was generated from the following files: <span>#include <math><</math>motor_controller_common.h<math>></math></span> === Public Attributes === int int int int === Member Data Documentation === [structmotor__control__manual__t_a8597d7c041893e079504242ac0b08c29] [structmotor__control__manual__t_aa7380bb84a6a6fee523aca85b5829c6e] [structmotor__control__manual__t_a72fcf12d4d5eca4ddb5ce536a27d1e18] [structmotor__control__manual__t_ae51a611a6ae54a081226f5960f55881a] The documentation for this struct was generated from the following file: <span>#include <math><</math>motor_controller_common.h<math>></math></span> === Public Attributes === int int int === Member Data Documentation === [structmotor__control__speed__t_ac869c864bab0a829fdb6e4979b5423d4] [structmotor__control__speed__t_abe11c48ec856b2c22d3874040743d1f5] [structmotor__control__speed__t_a17c66d80537c25ba0f0b91ee29aa441d] The documentation for this struct was generated from the following file: <span>#include <math><</math>motor_controller_common.h<math>></math></span> === Public Attributes === int char int int int int int int int int int int int int int int int int int int int int int int === Member Data Documentation === [structmotor__t_a8c4107c79b1e8be0bb867acb43f24dc2] [structmotor__t_ad10cf8ef2464c3948b63692c638220ac] [structmotor__t_a2da217bcba52c9f7730f547ce7b2f954] [structmotor__t_ab04b0231cc3d35441b9a550f6b709f37] [structmotor__t_aabc2e81419bf510dca8acdd9fdfb5fee] [structmotor__t_aa9d803b1dbe3ccc53502f498c67d0efd] [structmotor__t_a0b45561b3bd10d3fa5b967f27cc03b4d] [structmotor__t_a27a28d0b9cfa3d4df077d1b83b1ae50c] [structmotor__t_aa5e61f82d30c5beb67c3e4da63d3f973] [structmotor__t_a508cc8ca9efb12f6b7a2ca90c0145be3] [structmotor__t_ad9e0dad6c84f60b620b5c304f77a754e] [structmotor__t_ae1fd3fa15d93ee7ca77155e5065f19ae] [structmotor__t_a5aa7ba39f596fb84bc48ebe8bdf8742f] [structmotor__t_aa5663d6deb3ba03853ea1db9fee6d77a] [structmotor__t_af7acea56015c47320ad037a6447267a3] [structmotor__t_a01421ca52664b63fe5cf9045b31b5a93] [structmotor__t_af9f663b6c75e472266caa35a7327c7d9] [structmotor__t_a33267a8129db0fa1294a1e8411507b56] [structmotor__t_a228fe22eb14566279ab42ef21c8a056b] [structmotor__t_a7e8adeb92e7b56bec55778e93188b5ac] [structmotor__t_a633626a1a87f7660c37cfee774da143e] [structmotor__t_aef378823f8f766d89f79a12c1fad7298] [structmotor__t_afa5290085f6f4cbb82321b61f0e759e2] [structmotor__t_aa8f2bb71f13d25bd493f086b25d2a793] [structmotor__t_ab2e32b36075436b3d3022c2d08c6c7af] The documentation for this struct was generated from the following file: <span>#include <math><</math>motor_controller.h<math>></math></span> === Public Member Functions === <span>'''Initialize all Quad Motors'''</span> ''[_amgrpfce05aebd28fd6a36058c581a4d953d3] Initializes all four quad motors'' Uses the initQuadMotor to initialize all quad motors. void () <span>'''Initialize Quad Motor'''</span> ''[_amgrp1d644151bbcce9057e75fa35a143c31a] Intializes a specific propeller motor.'' The propeller motor is is initialized in open loop tapaziodal profile on the FPGA PWM generator. void (int motorNum) <span>'''Set Qaud Duty Cycle'''</span> ''[_amgrpf05c4be638915bb1f32e0410817774b6] Sets the quad motor duty cycle of a single quad motor.'' Sets the desired PWM generator block C to the desired duty cycle. <span>Parameters</span> is the desired PWM command is the intiger value for the motor number in the PWM generator C block. void (int pwmgen_value, int motor_num) <span>'''PID Control Calculator'''</span> ''[_amgrp9957f7bb2056d8a6c35ddf4083298f7b] Calculates the output of a PID controller.'' Runs a PID control algorithm on the struct. Doesn’t saturate the PID correction. <span>Parameters</span> A pointer to a struct <span>Returns</span> the controller output as a double double ( <math>\ast</math>pidptr) <span>'''PID Control Calculator with Filtering'''</span> ''[_amgrp14c8571050a8ae6f680e516dc4f4e5ac] Calculates the output of a PID controller with filtering.'' Runs a PID control algorithm on the struct. Doesn’t saturate the PID correction. Filtering is used in the derivative calcuation. <span>Parameters</span> A pointer to a struct <span>Returns</span> the controller output as a double double ( <math>\ast</math>pidptr) <span>'''Load Motor Controller Configuration'''</span> ''[_amgrp5f023cd0ca8b5dab8a80d84aba4ef6c6] Loads configuration data and initializes some controllers.'' Initializes controllers and filters needed for controller calculations. It reads in data from eris.cfg and other hard coded values. <span>Returns</span> 1 if sucessful int () <span>'''Arm Quad Motors'''</span> ''[_amgrp5c2ef70f6e4cadb7e720b01879f688a3] The quad motor ESC require an initialization sequence, this function creats that sequence.'' The ESC comands a cycled through a set of values to activate the ESCs. void () <span>'''Data Filter'''</span> ''[_amgrpd7dc50ca0736a594701687e8186067ab] Filter a data set using an FIR digital .'' Calcualtes an FIR used to data in the time domain. <span>Parameters</span> The point to the object to use The input data to the The output float (struct <math>\ast</math>, float data) <span>'''State Feedback Controller Calculator for 1D inverted pendulum'''</span> ''[_amgrp0537bb25e7f514750bffba69f7f4dba0] Calcuats the pole plavement controller for RADA'' Using the a (quad state space) struction it calcuates the controller output. This is for a 1D inverted pendulum. <span>Parameters</span> is a pointer to the structure to be used to calcualte the controller output. the contoller output as a double double ( <math>\ast</math>ssptr) <span>'''State Feedback Integral Controller Calculator for 1D inverted pendulum'''</span> ''[_amgrpf03ca3c2efc11db8bbd67d4f5cc8746c] Calcuats the pole plavement controller for RADA'' Using the a (quad state space with integration) struction it calcuates the controller output. This is for a 1D inverted pendulum. <span>Parameters</span> is a pointer to the structure to be used to calcualte the controller output. the contoller output as a double double ( <math>\ast</math>ssptr) <span>'''RADA LQI Controller Calcuator'''</span> ''[_amgrp078731063da6706b78f325db9a9695df] Calculates the LQI controller output with estimation.'' Filter the angular postion, calcuatetheangularrates, and then calcualte the controller outputs for the whole RADA system. <span>Parameters</span> is a pointer to the LQI controller structure <span>Returns</span> 1 as long as the controller is calculated int ( <math>\ast</math>lqiptr) <span>'''State Space Control Calculator'''</span> ''[_amgrpf6257f816f8d6d1766ce1561b15f352f] Caculatesthe state space controller (controller and estimator) comands.'' Calculate the controller output based off of the previous estimation and then estimate then ext step of the controller. <span>Parameters</span> is the pointer to the state space controller object <span>Returns</span> 1 if the controller calcultes the controller int ( <math>\ast</math>ctrlss) <span>'''State Space Controlelr Configuration'''</span> ''[_amgrpd94fd80ab4422727a101b6dc5baeb94a] Initializes a state space controller.'' This function initializes as state space controller (H2) that can track references or Dance depending on complier macros. 1 when the initialization is complete int () <span>'''MSP Packet Drop Controller Calculator'''</span> ''[_amgrpdef89e6ca047cb84488107cf20260329] Calcultes the MSP controlelr for lossy systems.'' Calcutes the value v2 (a set of inputs). Then calculate u2, a set ouf outputs. Next calculatev1_bar a set of inputs. Then calculate u1 a set of outputs. Then calculate Yo the scaled outputs that are sent to the actuators. Next calculate estimation of the next time step’s state. Finally, set these next step etimated states to thecurrent state estimation. <span>Parameters</span> is a pointer to the packet loss controller structure <span>Returns</span> 1 when the calculation completes int ( <math>\ast</math>ctrlss) <span>'''State Space Controller Configure for Packet Loss'''</span> ''[_amgrp37c81e75a7a9d084c58c456e7571158e] Configurs the Packet drop controller.'' Configures the initial state estimation, inputs, and outputs. <span>Returns</span> 1 when the controller structre is initialized int () <span>'''PID Control Calculator with Filtering and Variable Time Step'''</span> ''[_amgrp063a8faceb5db6e16b76dbd036348387] Calculates the output of a PID controller with filtering and time step calcuation.'' Runs a PID control algorithm on the struct. Doesn’t saturate the PID correction. Filtering is used in the derivative calcuation and calculating theactual time between controller calculations. <span>Parameters</span> A pointer to a struct The time between the last sample and now as a double <span>Returns</span> the controller output as a double double ( <math>\ast</math>pidptr, double dt) <span>'''RADA LQI Controller Calcuator with Variable Time'''</span> ''[_amgrpbcc1a735d18c2d59c7f5d9a769ad357e] Calculates the LQI controller output with estimation using theactual system dealt T.'' Filter the angular postion, calcuatetheangularrates, and then calcualte the controller outputs for the whole RADA system. <span>Parameters</span> is a pointer to the LQI controller structure is a double that is the time between samples <span>Returns</span> 1 as long as the controller is calculated int ( <math>\ast</math>lqiptr, double dt) <span>'''RADA LQI Controlelr with Estimator Calcuator'''</span> ''[_amgrp7500c88d96ef8d92553589505462fd1c] Calculates the LQI controller output with normal estimation.'' Calcualtes the controller output, estimate the next time step’s states. Set the current states to the next states. <span>Parameters</span> is a pointer to the LQI controller structure <span>Returns</span> 1 as long as the controller is calculated int ( <math>\ast</math>lqiptr) <span>'''LQG Controller Calculator'''</span> ''[_amgrp41ce89edf82c1d5162ec0a37eeb4a94a] Calculatesthe LQG controller for the whole RADA system.'' Calcultes the controller outputs using the previous time step’s estimation and the current inputs. Then it estimates the statesof the next time step. <span>Parameters</span> is the pointer to the LQG controller structure. <span>Returns</span> 1 once the calcution is complete int ( <math>\ast</math>ctrlss) <span>'''LQG Quad Controller Calculator'''</span> ''[_amgrp829e83dc64015e37961d2d115748c72e] Calculatesthe LQG controller for the whole pendulum system.'' Calcultes the controller outputs using the previous time step’s estimation and the current inputs. Then it estimates the statesof the next time step. <span>Parameters</span> is the pointer to the quad LQG controller structure. <span>Returns</span> 1 once the calcution is complete int ( <math>\ast</math>ctrlss) <span>'''LQG Eris Controller Calculator'''</span> ''[_amgrpc38c2a17da2f8813651939769b09ec53] Calculatesthe LQG controller for the whole Eris system.'' Calcultes the controller outputs using the previous time step’s estimation and the current inputs. Then it estimates the statesof the next time step. <span>Parameters</span> is the pointer to the eris LQG controller structure. <span>Returns</span> 1 once the calcution is complete int ( <math>\ast</math>ctrlss) <span>'''Initialize Motor Contorllers'''</span> ''[_amgrpd1997c79c23a3862511f6af22c0ec5da] This funtion initializes the motor controller strucures.'' Initializes the . If the mode is anything other than free, then the controller will attempt to acquire the motor device descriptors as defined in the Configuration object. <span>Returns</span> 1 on success, 0 otherwise int () void () <span>'''Stop Motors'''</span> ''[_amgrp3ef1bdab6ae253ecc163a825f4ea9e9f] Stops all motors.'' This will stop all quad and ground robot motors void () <span>'''Stop Ground Robot'''</span> ''[_amgrp5ca3b6a80bff934023e8810a002438b4] Stops all wheels.'' This will stop all ground robot motors. This is different from because the controller will still maintain the connection to the motor device descriptors, but the motors will be stopped. void () <span>'''Set Motors'''</span> ''[_amgrpdadd3c7c8f5910982d289bd98101684d] Sets the speed of the wheel motors.'' This will control the motors in a manual way, such that each motor can be controlled individually. <span>Parameters</span> The parameters for the movement command. void () void (const struct <math>\ast</math>command) void (const struct <math>\ast</math>command) void (float dt) void (MotorControl <math>\ast</math>packet) void () void () int () int () void (int useBoundsLimit) void (int useStatusLogging) === Private Member Functions === <span>'''Motor Controller default object'''</span> ''[_amgrp9e5257757bb47d5223c038f91d3ca39b] Creates a motor contorller object.'' Creates the object. Nothing is requested of the motor controller board at this ponint. () <span>'''Free Motor Controller bject'''</span> ''[_amgrp407b092ba9c174a55708b5d3e7ba1e6a] Deletes the motor contolelr object.'' Frees any resources used by the motor controller. () <span>'''Initialize One Wheel Motor'''</span> ''[_amgrpf5dc760419735c025a71fd62d74cb75f] Initializes one of the motot settings on the MESA board.'' Initializes one motor <span>Parameters</span> The motor structure to initialize void (struct &amp;motor) <span>'''Initialize All Wheel Motors'''</span> ''[_amgrp624dc6c5d4b272edbe3b43cae3f7e0ee] Initializes all wheels.'' Initializes all the motors void () === Static Private Attributes === static <math>\ast</math> = NULL === Motor Controller instance === Get the instance of the motor controller. Returns a single instance of the . <span>Returns</span> A single instance of the struct struct char char short short short short int int struct struct struct <math>\ast</math> <math>\ast</math> static <math>\ast</math> () === Set Motor Speeds === Passes the motor speed settings to the FPGA. Passes the motor speeds onto the motor board. After this command has been executed, the robot will begin to move. class class void (const char <math>\ast</math>name, const &amp;motor) void () static int (unsigned int degree) static int (unsigned int degree) === Constructor &amp; Destructor Documentation === [classMotorController_a1c32db157ba4b6dba1f2d6bc8891f16d] [classMotorController_ae4a6055b64466936c3576fb52fda9307] === Member Function Documentation === [classMotorController_add1bf5dae0eb05623df4b754d1c6fb49] [classMotorController_a93e60b0fa743ec1a6a69957d64689b55] Computes the output of cos(degree)<math>\ast</math>256 using a lookup table <span>Returns</span> (int)(cos(degree)<math>\ast</math>256 [classMotorController_a2553c87383d8241316ea2053fb12c7a4] [classMotorController_a48e1b88df6b0d6da8195ba102108d9d9] [classMotorController_a34520b22e1f3e4a6529133fb2481d32e] Gets if the motor controller is using bounds limiting <span>Returns</span> 1, if the korebot stops the motors when it leaves the bounds of the playing field, 0 otherwise [classMotorController_af3bade74d928cdddf29dbcaec33e9dba] Gets if the motor controller is logging status <span>Returns</span> 1, if the motor controller is logging, 0 otherwise [classMotorController_a4fecad722d049d29bc6efc6b4a549048] [classMotorController_a7e93f0790d37d266359cab27eaf19389] [classMotorController_a1772b5eb25ed867b6799c6488a1da283] [classMotorController_a6ea32666e8808436dc6d299a26e96d08] [classMotorController_a41163916eb76f85ea6d5c0bfeb0b0869] [classMotorController_ace062a26702f28230668809781e41039] [classMotorController_a712bfbc418522a2297053b16cd04ba3d] [classMotorController_a953b0bd7cf69a499d444e283cdcf2c6f] [classMotorController_a9b9cf813441e188fec5dde9783e4a56f] [classMotorController_ab64a7f9780e66317a624cdd945070b80] [classMotorController_a69d031076349d49d2a68de9d7a8ca8db] [classMotorController_a0b1e833f2acca5f4ca229edcdb982ba1] Prints the status of the given motor to console <span>Parameters</span> A human-readable description of the motor The motor details Prints the status of the given motor to console <span>Parameters</span> A human-readable description of the motor The motor details [classMotorController_ae350b355b22cd83ad7b735e456b146a9] Prints the status of various modules on the Korebot [classMotorController_a419d79a3fff2307b0ab96418270cbf92] Processes a packet received over the network <span>Parameters</span> The packet received from the network [classMotorController_a0e32982f7d58fc52a0bafe4f50572faa] [classMotorController_ad90235c67d1e809452589cba4b58f806] [classMotorController_a96915dcda6bfca14d18e523542982d49] [classMotorController_a2282991fb80e1689e1e7ffaa104015f2] [classMotorController_a0265a0be71190b23bdb591cde9c68097] Runs one iteration of the motor controller; Sets the speeds of the motors according to how the user / AI wants them to go. <span>Parameters</span> The time difference since the last call to this method [classMotorController_addb10f30dae3f4daeb0074b28f0ee1d1] Sends status information about the sensor manager to the control server. This includes the mode &amp; speeds of the motors. [classMotorController_a2e5e8ac28229cb8f9a0ce5f64a8d5b77] [classMotorController_a5abb6d80f4891452cbb6a3c7a3c32d5c] [classMotorController_a65dfcc468ce3529defe398fe7bf7392d] [classMotorController_ac9bd97a93cbe94bf844e80ef23056ad6] [classMotorController_a25f60534f1ef27d30f6cdf62519c791a] [classMotorController_a4e45155b4d2d208dc76967c304b7ebf3] Sets if the motor controller should stop the motors if the korebot leaves the bounds of the playing field <span>Parameters</span> 1, if the korebot should stay in-bounds, 0 otherwise [classMotorController_ab76a224b0d5188d15f33b6b697905933] Sets if the motor controller should log the status information to a file <span>Parameters</span> 1, if the motor controller should log, 0 otherwise [classMotorController_a41bec40abfaefa050d98ea4522945bd6] Shuts the motor controller down, destroying any resources &amp; releasing any devices the controller is holding. [classMotorController_a4635621e96ad618a1f33d02165cdfc9e] Computes the output of sin(degree)<math>\ast</math>256 using a lookup table <span>Returns</span> (int)(sin(degree)<math>\ast</math>256 [classMotorController_a50e55a6199c3cef74b5e8cd64039f315] [classMotorController_a69733631dbe8550b52933cc03fcb0f54] [classMotorController_aab0247df4f0413a46e68ada1e3b4e991] [classMotorController_a3b1f06b4d39a840887079ce725401162] [classMotorController_a46b269cc3a363a8a621e3f50aef79963] [classMotorController_af0e455864d2af2f4f293961d95b843a1] [classMotorController_a317ce58ea93ea1329de5b87391560082] [classMotorController_a1296842f7e49211c6dd36023967e8ac2] === Friends And Related Function Documentation === [classMotorController_a0191eec9042e10ff1da22f98f14498fb] [classMotorController_a56b5005fdfe78e27f0ecd4d7d876b646] === Member Data Documentation === [classMotorController_a1d97bedd5ac33c60ecb00442569b0ada] [classMotorController_a746ddd1d96190bbc14669d555ae1ed11] [classMotorController_af9ad9c5897f6fc801694837c2ecce6e5] [classMotorController_ab78c465d4e96d3c8b21b08fa8b2f5589] [classMotorController_a915f7c7db7eafe922c183f0a008ae53a] [classMotorController_a07e3f68c416a983de11e401b5c0f1433] [classMotorController_a77bd609c9cce4b00533f00eb3b4b9197] [classMotorController_ac14cc62eae3a30fc2752a78fbd18a6e8] [classMotorController_ad49cd20423752fe17d45abca19fcd5f8] [classMotorController_aa53faa6f4491dcdc8fbcaa22ca0498d5] [classMotorController_a7dfcbab99afde391b774d444f603fb5b] [classMotorController_a12e46cfc455ac7e814a977d244be5f08] [classMotorController_a824e25371c790d050dc68a8ca861ac17] [classMotorController_ac455cbf551bd87ff0e7b9647d3e29caa] [classMotorController_a1d266c8a0c0bd8d1a123fe92eadac4b4] [classMotorController_a34ba46e538027b3897d8a52c432acea8] The documentation for this class was generated from the following files: <span>#include <math><</math>motor_controller_common.h<math>></math></span> === Public Attributes === struct struct struct struct === Member Data Documentation === [structmotortrain__t_ac93c32e936810c89d906a780388fa543] [structmotortrain__t_a936dab25cd19cd882c1f4b5547f6854d] [structmotortrain__t_a0975c7dc29c06eb3e41c7b3d2d89f897] [structmotortrain__t_a7374ec1fab1a3b24ab05f4f3f562286a] [structmotortrain__t_a17d91b9941dd97fe08ac5f05d320db77] [structmotortrain__t_a1bf8fd344ea4ab736e8be74807f28ce8] [structmotortrain__t_aa512d3487dad0e44ba34f7bd80644989] The documentation for this struct was generated from the following file: <span>#include <math><</math>motor_controller_common.h<math>></math></span> === Public Attributes === double double double double double double int int int int double double double double struct struct struct int int === Member Data Documentation === [structQUAD_a2eed9f1713c43f7c7491813afe60d159] [structQUAD_a00d9ad43243a8079bdafc17bad61e8a8] [structQUAD_a10e64234abe44400db28b86cccf71b9c] [structQUAD_a37a8faccecc87a0a36db7758aebd4cd3] [structQUAD_ab6322c69c61e8c52113215b8782f5640] [structQUAD_a1c0d275153c7e8f6a96cb438c57de6fb] [structQUAD_a8e0ab0fca05fa4368e9c142b879165b8] [structQUAD_aae593162318a8f85cee245d36384e43e] [structQUAD_a8fb550e3a46fca686af955f7070891d5] [structQUAD_aa39e1ed5847afe259a4bed63fdcdcdb2] [structQUAD_af0a105f1ee7eb97eab0db1b5e1996f37] [structQUAD_a1e4d41cb80153a8d7cd81c66c98c8b3a] [structQUAD_adefa68d6df6fb3288bce229cad63eaa3] [structQUAD_a2f1b6a7383290f5c552eef5e51825a35] [structQUAD_ae9bb78262875c8a49b7c1ce6eba1691f] [structQUAD_a5d6a99d953ddbc2f0e0d799459afbe0b] [structQUAD_a893e505f05bad2f5904387c926f12c8c] [structQUAD_a5f2425f4d2370d30a963157527e2bf9c] [structQUAD_ae7f289e91404a2f165d2f7c6a25a8450] [structQUAD_aa8a9da65a487c47e81c77b33323428ef] [structQUAD_ae2c9ab465e6ebfe2a26122cc3caf15d7] [structQUAD_a17071969d4bc2093b3d2fc1ee83af04d] [structQUAD_a5150d2569d431a1380cb7d837e96ebf5] [structQUAD_ace794fbc91c3193f6e5e42d1f8e2cd64] [structQUAD_a754e8f9b57794e2ab9b4c3542e39464d] [structQUAD_a79b59140f8b04dac9218dcc699f5b3f8] [structQUAD_a2449ef626bfeca6b8a7c63fcbc2c6818] [structQUAD_a542aee3387201368593832b4e47ba743] [structQUAD_a883c6b66339a648916033d296368f9dc] [structQUAD_aedc6dc7e5aa35ef51d1ced2dce9513a0] [structQUAD_a2ab750ab10497d939cdddba72cfc4de6] The documentation for this struct was generated from the following file: <span>#include <math><</math>motor_controller_common.h<math>></math></span> === Public Attributes === double 6 double 6 double 4 double 2 double double === Member Data Documentation === [structQUAD__LQG_a76bbbb078df43082bbd27354d9458b9d] [structQUAD__LQG_ae06b105072a09fdfe8bf26f6db82e1d3] [structQUAD__LQG_a34c2cd67f46354f4dd1390ceb13d8639] [structQUAD__LQG_ab2510335708e94ce453625ec6c88a8f4] [structQUAD__LQG_a45f38782147369b8b6df1999ebdcfa17] [structQUAD__LQG_ac031b1e1bb3c1e293c422eb66f388f39] The documentation for this struct was generated from the following file: <span>#include <math><</math>motor_controller_common.h<math>></math></span> === Public Attributes === double double double double double double double double double double double double double double double double double double double double double === Member Data Documentation === [structQUADPID_af57693675d3b91e74c7fce833c2d3229] [structQUADPID_a37120d7ed179891e570632dde992a62d] [structQUADPID_aebe069933b736158b6e9c66480b5dd66] [structQUADPID_a9e340ef1ec326c3ea24ab853eaab5356] [structQUADPID_a8c459e89dad8aba573f629a2eee95a2e] [structQUADPID_a53abc22b47daebd646ffa93edeebabf3] [structQUADPID_a15a2c22f71f430b0f3da088fdaf11e8b] [structQUADPID_a35bd258abd8b446cf0fc7192f5444ace] [structQUADPID_aad48c2639f5e7f7a7507a65f2fc9f840] [structQUADPID_af0c37cfc4dd8de23ea8e1f5a9dde49ca] [structQUADPID_ac0ca662a0fd18d9a7ae9be60f16642aa] [structQUADPID_a4e96ee985a438bbac5a5a2e7c20a6ba3] [structQUADPID_ac2322202d22bfef5a2bac06ab69ad04e] [structQUADPID_adffd1a7f278135c8b1dbe8ed3c028d49] [structQUADPID_a641e3400a556ef67ae641bb748f35502] [structQUADPID_a37ec2314c8e6ea28ce2bf9677bac90c3] [structQUADPID_ae2363c0b0775bd8139ba5768470b986d] [structQUADPID_a074e9f874f299cd53447a34638c0daad] [structQUADPID_ad2e9f72912b4f53ec0a6c57652706a9f] [structQUADPID_a5b2c0619378b80766a76fe248d4e82cf] [structQUADPID_a52b5fb6398fecd60c22bedd8b5c88554] The documentation for this struct was generated from the following file: <span>#include <math><</math>motor_controller_common.h<math>></math></span> === Public Attributes === double double double double double double double double === Member Data Documentation === [structQUADSS_add3c0c29d0b5a86bc0650e10048da943] [structQUADSS_aea9e3c78961e8d18c5a5b0e7801a3757] [structQUADSS_a429e966bc34c1bdc2277139488b777d6] [structQUADSS_aedab9a84e7fe0fc90e9fb6573f92edc9] [structQUADSS_a82100cd859c1d02e9a0610610f9ce598] [structQUADSS_a848a1f6b9b1386b06cbc1545a8a850bf] [structQUADSS_a5184771429743ed0518c4cb93764bdc1] [structQUADSS_a4586121326628ddd1183bb6bf7bbcf39] The documentation for this struct was generated from the following file: <span>#include <math><</math>motor_controller_common.h<math>></math></span> === Public Attributes === double double double double double double double double double double double === Member Data Documentation === [structQUADSSI_a578f581dca979d890f092a5276c1de2e] [structQUADSSI_a4226d40c10573f3f827ae7666ef1fc44] [structQUADSSI_a9abfe43101a30f54fe2d38d60de74b2c] [structQUADSSI_a2c5a14aeaeee20b7f0a28f519bb88ba3] [structQUADSSI_ac85d5d5297bdae061cafd99d3a1735c5] [structQUADSSI_a16756c462227bebb2eada031f7926249] [structQUADSSI_adbc07d19432895cd041db18a418ed9ac] [structQUADSSI_a474e0b411cc0f122694e51d1b0659acf] [structQUADSSI_abece16790d7a4e8a8ca59afb9448c370] [structQUADSSI_a45e12800b609b4a4f8b3bac4566695cc] [structQUADSSI_a4a270033dec1ba6e9339ae6165389c9f] The documentation for this struct was generated from the following file: <span>#include <math><</math>motor_controller_common.h<math>></math></span> === Public Attributes === double 13 double 13 double 10 double 5 === Member Data Documentation === [structRADALQG_aa940eeca8f5baac2249898725297a0d0] [structRADALQG_af266d468cac40fa2d420f8bfddd7b557] [structRADALQG_ae3d7654593c0ce69332c8a60ea4cb4b7] [structRADALQG_a71dff35bb7444784fa6a4fb0abfd79e6] The documentation for this struct was generated from the following file: <span>#include <math><</math>motor_controller_common.h<math>></math></span> === Public Attributes === double double double double double double double double double double double double double double 8 double 8 double 5 double 513 double 5 double double double double double double double double double double double double double double double double double === Member Data Documentation === [structRADALQI_afdcf53ebe9bcecebb6672e3477bf3033] [structRADALQI_a951609272a5a9521d530b01e9ef09595] [structRADALQI_a3db98fefec3bacd77109ed872770ee52] [structRADALQI_a5c8328044c5e72bd14586d7518597d86] [structRADALQI_a03256a0ae4e91b1be17aff1e5fe5d97e] [structRADALQI_a187690a16632205e125a65ad4c446eb0] [structRADALQI_a923333c98a36453319870d2c3c41e664] [structRADALQI_a7553fcb3e6b678243cb011c35b8f7654] [structRADALQI_aa922b81415119cbcc3bc2cda233187aa] [structRADALQI_ac7c14eccdd17f87c18fc0d3c5a9fbeff] [structRADALQI_a6da18a4d7a2ce4036df91f6dadff1046] [structRADALQI_a4a8c3336e535d69214c5b1544cff8a4f] [structRADALQI_a029c912330265d6601207a31b673ac2e] [structRADALQI_ab8db739fd43babe83c86aaccdee03107] [structRADALQI_ac3ba42e78de0c7a9f9bac06ee59d9af7] [structRADALQI_a38be3a08ecdef8905bf026197ec2d001] [structRADALQI_a00e509effa31ce836d84e8ac44691237] [structRADALQI_a5f04861fdd822873fddfbb9b8ed6e1ac] [structRADALQI_a295076da380631add54edc56a0720cf1] [structRADALQI_a2ac030254978e192ed3a511324dd5dc6] [structRADALQI_a9e3250b14c3c011c300dff35b7358558] [structRADALQI_ad58dffb99676bd9adb92bc5af8bb1c70] [structRADALQI_a7b2374ca0e9ccfeb1beb1d272b39b0b4] [structRADALQI_aef3f073773528798287820fd58976d14] [structRADALQI_a97aa272c346c35631ca4564a37124dc5] [structRADALQI_a229c3294975da8be631e9e11107c37af] [structRADALQI_a8d61dd4ba5cd4475c5146bd11b467a9b] [structRADALQI_a15fb171c13f71768f9919b8f1f691dd3] [structRADALQI_a48be324b5e318ac948cc745350b2d234] [structRADALQI_adafde08ed92f42256ca80f4c62d61614] [structRADALQI_a2885d192d345fbc7b2032b3ddaf6adfd] [structRADALQI_a469a7e328410a7a783338c6609d8cc06] [structRADALQI_aa93908270a2fa6ab0e608ce60c68f47f] [structRADALQI_acdc45aaafc81cd9d721e7fcb8eecb746] [structRADALQI_a99de43ecd01f525e3c3e25c61a81d842] The documentation for this struct was generated from the following file: <span>#include <math><</math>vrpn.h<math>></math></span> === Public Attributes === double float float float float float float === Member Data Documentation === [structvrpn__data__t_a36832473aff982b334e73ef8f2107975] [structvrpn__data__t_a174930b2f9de89327cbd168ecc288da2] [structvrpn__data__t_aef6531470caa7a95e650b19ed0139ae6] [structvrpn__data__t_a5a5a96aa9d0640599eb1d950e8e4c833] [structvrpn__data__t_a5faf10d13f8203d5d34ed0ac580d50ee] [structvrpn__data__t_a643aa072522e303a9d9cd7637d8632a0] [structvrpn__data__t_a9b71e15122a1d3fa495f5e6a797c7084] The documentation for this struct was generated from the following file: = File Documentation = This clss dercribes the key bindings for the UI. === Classes === class === Detailed Description === This clss dercribes the key bindings for the UI. <span>Author</span> Dylan Gransee, Robert Larsen <span>Date</span> July, 2016 This class holds the key bindings for the command line interface. Changes and additions can easily be made by anyone who does not like the available commands. The different sets may have the same command because you can only use one set of commands at once. Code that logs data from RADA system tests. <span>#include <math><</math>iomanip<math>></math></span> <span>#include ‘&quot;logger.h‘&quot;</span> <span>#include <math><</math>iostream<math>></math></span> <span>#include <math><</math>string<math>></math></span> <span>#include <math><</math>sys/stat.h<math>></math></span> <span>#include ‘&quot;utils.h‘&quot;</span> === Variables === struct const string = ‘&quot;<math>\backslash</math>033H<math>\backslash</math>033J‘&quot; === Detailed Description === Code that logs data from RADA system tests. <span>Author</span> Paul Uhing, Ian McInerney, Dylan Gransee, Robert Larsen <span>Date</span> July, 2016 This file logs data to a text file in the Eris directory /root/Logs/ErisDate/log(timestamp).txt There are some compiler macros for configuring the logger. They must be set in Logger.cpp because Paul Uhing couldn’t get the macros in to work in . . ssDrop makes the logger log data for the MSP packet drop controller. RADAlqi_est causes the lager to log controller inforamtion about a LQI controller . RADAlqi_est causes the lager to log controller inforamtion about a LQI controller with a traditional estimator. rada_lqg causes the logger to log data about the LQG controller for the whole system. rada_split_lqg causes logger to log data about the seperate LQG controllers. rada_split_lqg_ol causes the logger to log data about a LQG controller and the Eris to control its yaw with a PID and the linear velocities are controlled through open-loop commands. H2ctrl cause the logger to log data about a H2 controller. If ssDrop, H2ctrl, RADAlqi, RADAlqi_est, rada_lqg, rada_split_lqg, or rada_split_lqg_ol are not defined then RADA will default to PID control. === Variable Documentation === [logger_8cpp_ae565de10fdcd13a32c3deef98b10b045] [logger_8cpp_a57e5a12456f314ffc728d5d8da312970] <span>#include <math><</math>fstream<math>></math></span> <span>#include ‘&quot;motor_controller.h‘&quot;</span> === Classes === class main code that controls the data flow for running RADA <span>#include <math><</math>iomanip<math>></math></span> <span>#include <math><</math>iostream<math>></math></span> <span>#include <math><</math>string<math>></math></span> <span>#include <math><</math>cstdlib<math>></math></span> <span>#include <math><</math>cstdio<math>></math></span> <span>#include <math><</math>pthread.h<math>></math></span> <span>#include <math><</math>quat.h<math>></math></span> <span>#include <math><</math>signal.h<math>></math></span> <span>#include <math><</math>ctime<math>></math></span> <span>#include ‘&quot;configuration.h‘&quot;</span> <span>#include ‘&quot;korebot.h‘&quot;</span> <span>#include ‘&quot;logger.h‘&quot;</span> <span>#include ‘&quot;motor_controller.h‘&quot;</span> <span>#include ‘&quot;utils.h‘&quot;</span> <span>#include ‘&quot;vrpn.h‘&quot;</span> <span>#include ‘&quot;key_bindings.h‘&quot;</span> <span>#include ‘&quot;sensor_manager.h‘&quot;</span> <span>#include ‘&quot;sensor_manager_common.h‘&quot;</span> <span>#include <math><</math>math.h<math>></math></span> === Defines === #define #define  26000 #define  56000 #define  65535 #define  ((DUTY_CYCLE_MAX - DUTY_CYCLE_MIN) / 2) + DUTY_CYCLE_MIN #define  (DUTY_CYCLE_MAX - DUTY_CYCLE_MIN) / 2 #define  6656 #define  26880 === Enumerations === enum { , } enum { , , , } === Functions === <span>'''Handle pendulum postion VRPN callback'''</span> ''[_amgrp37d875ee3807f019e19d2d6dee41a566] Preocesses the pendulum VRPN data.'' vrpn callback function that is called everytime vrpn data of the pendulum is received. The callback gets the data and calls the pid controller by passing that data in. <span>Parameters</span> no clue what this is the vrpn data that was received void VRPN_CALLBACK (void <math>\ast</math>, const vrpn_TRACKERCB t) <span>'''Handle Eris VRPN callback'''</span> ''[_amgrpe6e20aba9f601fcbc946d140a2025da7] Processes the camera system data for Eris from VRPN.'' vrpn callback function that is called everytime vrpn data of Eris is received. The callback gets the data and calls the pid controller by passing that data in. <span>Parameters</span> no clue what this is the vrpn data that was received void VRPN_CALLBACK (void <math>\ast</math>, const vrpn_TRACKERCB t) <span>'''Main thread UI control'''</span> ''[_amgrpf3df38af8777b52967885581a6bf5072] Handels the user input and data printed for the user.'' This thread prints of data to the user and checks for user input the changes control modes and references. In the Stopped mode the thread is looking for the user to request entry in to the other modes or exit the program. It also stops the VRPN thread from executing. In tuning mode the user will be allowed to tune the pendulum PIDs. In Robot control mode the user can give commands to manuver Eris. In Box step mode the pendulum goes through a series of setpoint steps. The escape key will cause the program to stop. <span>Parameters</span> is a pointer to the thread ID of theis thread. void <math>\ast</math> (void <math>\ast</math>threadID) <span>'''Control Loop Thread'''</span> ''[_amgrp4e6e712710141b9bb1acc2a64aef0639] The main function for the control loop thread.'' This thread should be used if the packet drop code is ever edited to work with a real fading network. It should be implimented such that the controller will run every 10ms and determine if there has been packet loss <span>Parameters</span> is the thread ID void <math>\ast</math> (void <math>\ast</math>threadID) <span>'''Pendulum PID controller calcualtion'''</span> ''[_amgrp9fc67c72cd599f172740e6b41f919d72] Calculates PID controller for the Pendulum commands.'' This function sets up the calculation of the desired PID controller for the pendulum commands then calls the controller function. Finaly it converts the controller output to valid actuator commands and sens these commands to the actuators. <span>Parameters</span> the vrpn data of Eris void ( <math>\ast</math>vrpnData) <span>'''Eris PID controller calcualtion'''</span> ''[_amgrp966797ce8643a3dd9f9c9be64292a6f5] Calculates a PID controller for the Eris system.'' This function sets up the calculation of the desired PID controllers for Eris then calls the controller function. Finaly it converts the controller output to valid actuator commands and sens these commands to the actuators. <span>Parameters</span> the ponter to the vrpn data of Eris void ( <math>\ast</math>vrpnData) <span>'''User PID Tuner'''</span> ''[_amgrp19c4ee08c9dbcdaf609dc0a72c72d089] Used to tune the pendulum PIDs'' This UI is used to tune the pendulum PIDs. It doesn’t perminatly change the PID values in eris.cfg. You can also swithc control mode <span>Parameters</span> pionter to the pendulum vrpn data void ( <math>\ast</math>vrpnData) <span>'''Robot Control User Interface'''</span> ''[_amgrp1252ccc3177db21404c6dc4ed6a4eaa4] Lets users command Eris to move and change headding.'' The user can command Eris to move in x/y and rotate. The user can also change the command mode. <span>Parameters</span> The pointer to the pendulum VRPN data void ( <math>\ast</math>vrpnData) <span>'''Robot Control Mode'''</span> ''[_amgrp74ce911b6d1d37b44c2b8ce61152513b] Handles user inputs in robot control mode'' This function processes the user input from the UI when in rop=bot control mode. void () <span>'''Tuning Mode'''</span> ''[_amgrpb934e8737cc509085ebb5f73b19acb1c] Hadles the user inputs when in tuning mode'' This function handers the user input when in tuning mode. void () <span>'''Pendulum Box Step Mode'''</span> ''[_amgrp0dd1499b5cddba7f94d7e8d3984cd1c7] Causes the pendulum to move in a box when in PID mode.'' This function performs a demo by moving in a box formation (first moves to a corner from center, then steps around in a square). It takes 9 steps to be centered again. This function uses the following global variables nextChange - Time in seconds of the next state change state - The current state - the position in the box boxSize - Angle size in radians of the box changeRate - Time in seconds between each state change <span>Parameters</span> is the current vrpn time void (double curTime) <span>'''Load Configuation Files'''</span> ''[_amgrped311958465031c00fa547e89c46a708] Loads eris.cfg from the NFS'' Lods the configuration file in the Configuration class <span>Returns</span> bool value that for success or failure bool () <span>'''UI Thread'''</span> ''[_amgrp62c5d6af5e738187ff22ed2cdba8093e] This is the main function for hte UI thread'' This thread just waits for user input (in the form of a single keypress). Once input is received, a global variable for the key is set so that the main thread can access the key that was pressed. <span>Parameters</span> is the thread ID <span>Returns</span> NULL since it shouldn’t end in our case void <math>\ast</math> (void <math>\ast</math>threadID) <span>'''ctrl+c handler'''</span> ''[_amgrp99eb6333e039b04cc2ae3b28102e0bfa] this function exits the program correctly even when exiting via ctrl+c.'' This is a ctrl+c handler. It sets app_shutdown to 1, which should shut down the program. I am not sure of the specifics because this was written before the May15-27 team <span>Parameters</span> the signal that it receives when the key is pressed static void (int sig) <span>'''RADA LQI controller calcualtion'''</span> ''[_amgrpe30a3a342484e25b238d7c5cd8c27cbb] Calculates a LQI controller for the entier RADA system.'' This function sets up the calculation of the desired LQI controller then calls the controller function. Finaly it converts the controller output to valid actuator commands and sens these commands to the actuators. <span>Parameters</span> the vrpn data of the pendulum the vrpn data of Eris void ( <math>\ast</math>vrpnDataPen, <math>\ast</math>vrpnDataEris) <span>'''RADA State-space controller calcualtion'''</span> ''[_amgrp23542f9ec756f55caa3591c437bfac56] Calculates a state-space controller for the entier RADA system.'' This function sets up the calculation of the desired state space controller then calls the controller function. Finaly it converts the controller output to valid actuator commands and sens these commands to the actuators. <span>Parameters</span> the vrpn data of the pendulum the vrpn data of Eris void ( <math>\ast</math>vrpnDataPen, <math>\ast</math>vrpnDataEris) <span>'''RADA State-space controller calcualtion with packet loss'''</span> ''[_amgrpf56561d2b664983cbfcb2c50e691a9d8] Calculates a state-space controller for the entier RADA system under lossy conditions.'' This function sets up the calculation of the desired state space controller then calls the controller function. Finaly it converts the controller output to valid actuator commands and sens these commands to the actuators. <span>Parameters</span> the vrpn data of the pendulum the vrpn data of Eris void ( <math>\ast</math>vrpnDataPen, <math>\ast</math>vrpnDataEris) <span>'''Test propellers at 50% commands'''</span> ''[_amgrp467ef14d3f83635ee95aefccc1c11b89] Runs the propeller motors at 50% of maximum command.'' The motors are tested at 50% of maximum command to determine what the effective batter voltage the ESCs see. This sould only be used to with the battery voltage measuing setup for te quadrotor in Chapter 5 of Paul hing’s thesis. void () <span>'''RADA LQI controller with esitmation calcualtion'''</span> ''[_amgrp44e159876fd6aed6675462ea834d4ada] Calculates a LQI controller for the entier RADA system with esitmation.'' This function sets up the calculation of the desired LQI controller with esitmator, then calls the controller function. Finaly it converts the controller output to valid actuator commands and sens these commands to the actuators. <span>Parameters</span> the vrpn data of the pendulum the vrpn data of Eris void ( <math>\ast</math>vrpnDataPen, <math>\ast</math>vrpnDataEris) <span>'''RADA LQG controller calcualtion'''</span> ''[_amgrpa91cac312d6bef2eb5e7e736994f4383] Calculates a LQG controller for the entier RADA system.'' This function sets up the calculation of the desired LQG controller then calls the controller function. Finaly it converts the controller output to valid actuator commands and sens these commands to the actuators. <span>Parameters</span> the vrpn data of the pendulum the vrpn data of Eris void ( <math>\ast</math>vrpnDataPen, <math>\ast</math>vrpnDataEris) <span>'''Quadror LQG controller calcualtion'''</span> ''[_amgrp45f126903f6b8cbbb39832621800abd6] Calculates a LQG controller for the pendulum system.'' This function sets up the calculation of the desired LQG controller for the penduum then calls the controller function. Finaly it converts the controller output to valid actuator commands and sens these commands to the actuators. <span>Parameters</span> the vrpn data of the pendulums void ( <math>\ast</math>vrpnDataPen) <span>'''LQG controller calcualtion for Eris only'''</span> ''[_amgrp2fcbbf0d43176e1469cdb7ef2c01215d] Calculates a LQG controller for the Eris system.'' This function sets up the calculation of the desired LQG controller for Eris then calls the controller function. Finaly it converts the controller output to valid actuator commands and sens these commands to the actuators. <span>Parameters</span> the vrpn data of Eris void ( <math>\ast</math>vrpnDataEris) <span>'''Eris PID controller with open-loop calcualtion'''</span> ''[_amgrp5d5162a153e3702020f806e0b98a335a] Calculates PID controller for Eris with open-loop commands.'' This function sets up the calculation of the desired PID controller for Eris with open-loop commands then calls the controller function. Finaly it converts the controller output to valid actuator commands and sens these commands to the actuators. <span>Parameters</span> the vrpn data of Eris void ( <math>\ast</math>vrpnData) <span>'''Tic stopwatch starts'''</span> ''[_amgrpbe5fa55475c3c5cd3d3dde119cd0c839] Starts a stopwatch timer.'' This function will get the current time to start timing something. Example Usage: tic(); do_things; toc(); deltT(): void () <span>'''Toc stopwatch stops'''</span> ''[_amgrp7282852836645082f4d2dc3a1ee2f48f] Stops a stopwatch timer.'' This function will get the current time to stop timing something. Example Usage: tic(); do_things; toc(); deltT(): void () <span>'''Delta T stopwatch output'''</span> ''[_amgrp6c89f10ad681f33bea46252ec9ef66c1] Prints the length of execution of the last set of timed code.'' This function take the diefference between the start time and stop time and convert that to time in milliseconds. Then the function prints the time to the STD Out. Example Usage: tic(); do_things; toc(); deltT(): void () <span>'''Main function of RADA'''</span> ''[_amgrp9789cfd4cd4c15da3d3fa22ebb5abadd] This function intitializes the RADA test and hands execution to the threads.'' This function intializes the code execution by loading the configuration, intializing the motor controller settings, the , VRPN, and then hands the execution for the code to the VRPN thread and the main thread. The main tread is in charge of text based UI the user interacts with over SSH. The vrpn thread handles processing the VRPN data including controller calcualtions. There could be a thrid thread added to garentee that the packet drop controller runs every 10ms when packet drop controllers are run in a real enviorment (not simulating drops). int (int argc, char <math>\ast</math><math>\ast</math>argv) === Variables === int pthread_mutex_t pthread_mutex_t static char const string = ‘&quot;<math>\backslash</math>033H<math>\backslash</math>033J‘&quot; static double = 0 static = STOPPED static = STOPPED static FILE <math>\ast</math> static unsigned char 2 static size_t static ssize_t static unsigned char = 0 static unsigned char = 0 = PITCH static double = 0 static double = 20 static int = 0 static float = 0.0872664626 struct static int = 35 static int = 0 static float = 9<math>\ast</math>0.0872664626 struct timeval startt long long double === Detailed Description === main code that controls the data flow for running RADA <span>Author</span> Paul Uhing, Ian McInerney, Dylan Gransee, Robert Larsen <span>Date</span> July, 2016 This file setsup and controls the execution of the RADA system on Eris. ssTracking setsup reference tracking of inputs to control RADA when under H2 control. ssDrop puts the code in to packed drop mode and then RADA is controlled by a packed drop MSP controller. drop10 has the packet drop controller use a 10% drop controller design and forces the loss of 10% of packests. drop30 has the packet drop controller use a 30% drop controller design and forces the loss of 30% of packests. drop50 has the packet drop controller use a 50% drop controller design and forces the loss of 50% of packests. mot50 is used to test the actual propeller battery voltage at the ESCs after a test. The propellers are run at 50% command and the wheels are not commanded. RADAlqi causes RADA to be controlled by an LQI controller. FIR filters ae used to estimate velocities. RADAlqi_est causes RADA to be controlled by an LQI controller with a traditional estimator. rada_lqg causes RADA to be controlled by an LQG controller for the whole system. rada_split_lqg causes the pendulum and eris to be controlled by seperate LQG controllers. rada_split_lqg_ol causes the pendulum to be controlled by a LQG controller and the Eris to control its yaw with a PID and the linear velocities are controlled through open-loop commands. yaw_off turns off yaw control of Eris. H2ctrl puts RADA into a mode that uses an H2 controller to control RADA. ssMotors has RADA use an H2 controller that has propeller motor states in the controller design and will cause the system to ‘&quot;dance.‘&quot; accR sets up an acceration ramp for eris velocity control. posRamp causes Eris to control velocity as a postion ramp. If ssDrop, H2ctrl, RADAlqi, RADAlqi_est, rada_lqg, rada_split_lqg, or rada_split_lqg_ol are not defined then RADA will default to PID control. Make sure to edit the defines in to match the controllers used here. === Define Documentation === [main_8cpp_a4e084139c6a2952b2d8e3926f7a5d4dd] [main_8cpp_a994d9f112b804790cb294940eb9d323b] [main_8cpp_adea6f9fd5cbfe15ba103162c938c82c1] [main_8cpp_ad6c255586afaadad77cc9ead98c4c3ef] [main_8cpp_ad83c5423508a0de5baa15de51dda7dc5] [main_8cpp_a89551354e91f5016b1abcfaf16e940a3] [main_8cpp_a1ec7940bd8e2d994ebe311607d8300c9] [main_8cpp_a2a7307f445fd64358b32c0e3b7c1d97b] === Enumeration Type Documentation === [main_8cpp_ae3996976d8ffb3e58d88f58227473f8e] ; <span> ''[main_8cpp_ae3996976d8ffb3e58d88f58227473f8ea2eeb9fef8a6a516fa6437a44a6efbd52]'' </span> : ; <span> ''[main_8cpp_ae3996976d8ffb3e58d88f58227473f8eaa4ed247aa19723caf868d2b2dd5cf4ff]'' </span> : [main_8cpp_a46c8a310cf4c094f8c80e1cb8dc1f911] ; <span> ''[main_8cpp_a46c8a310cf4c094f8c80e1cb8dc1f911a948b2aee15f52b421fa4770c47bcfe8c]'' </span> : ; <span> ''[main_8cpp_a46c8a310cf4c094f8c80e1cb8dc1f911a5b098db3405ab997f1df697c8a25af60]'' </span> : ; <span> ''[main_8cpp_a46c8a310cf4c094f8c80e1cb8dc1f911a8a1be19211abeacf191fa94e53a88df7]'' </span> : ; <span> ''[main_8cpp_a46c8a310cf4c094f8c80e1cb8dc1f911a3f7641d93f9edd6dcef0ecbc9e5bcac2]'' </span> : === Function Documentation === [main_8cpp_a21bf4fc6c3a34c923d42af1dd5980075] [main_8cpp_ace0ab8e44bfaa97bfcd82adb89d74854] [main_8cpp_ac9f02fb0114292a308e093f0d9f8aa30] [main_8cpp_adb0f7bc1fa10ac859582e433e7acc7dc] [main_8cpp_a1dbdf224e16e0509ac19e34c27bc37e7] [main_8cpp_aa19799b0e80b4e69de6b6cc3ade092c1] [main_8cpp_aac75d50db164b40415d3d80142fc4d2c] [main_8cpp_a4a20cd0821f9530e40398374ca1a4311] [main_8cpp_a3c04138a5bfe5d72780bb7e82a18e627] [main_8cpp_a568000bf542342c7b00ddb00afb93fd9] [main_8cpp_aa8c69f9e4a04bdaa5ce904551cae390d] [main_8cpp_ac94b9d8c47c3b310cd58bd94b0133783] <math>\ast</math> [main_8cpp_a5669af9fd1cb16cbafe7bba476401d1e] [main_8cpp_aa48cf9381fdd01af90024b19545df7d4] [main_8cpp_aa8d50bf6758495a8070ea25c1e37e7f9] [main_8cpp_a728c70f1946e291f107c8c6e7a2ea65e] [main_8cpp_a1075d00c4632a01409111682ed506a4b] [main_8cpp_a16b090c977019835b449e0113e61a29b] [main_8cpp_a23c4b3cc92e1574ab3fd5522a51f274f] [main_8cpp_a898ef4198c44ab81d796a247d6a61458] [main_8cpp_ab5a1f466bba3d4b5cffc3697c11d218f] [main_8cpp_a7424442480a606c0febd38ec999c6af8] [main_8cpp_a5ba73899fe15846cc99820005d978e24] [main_8cpp_a3f604b0d492a343dd2c72ca7469b3cf7] [main_8cpp_a8f66738d39f61b6992e622acb683de6a] [main_8cpp_a6a64e00f10edf7b5f98ecae52de3427e] [main_8cpp_a40769a58f3fc191e9913aa92d53f527d] === Variable Documentation === [main_8cpp_ac32d6ad6c0714685f04b0130c7f77553] [main_8cpp_ad51e2c30d9b96de16e744f7ca54f3413] [main_8cpp_a4189bb97da233315f5721d38f82f10fe] [main_8cpp_ae565de10fdcd13a32c3deef98b10b045] [main_8cpp_a5d055a05b7de1e0898d6da92e2725e5e] [main_8cpp_a4565889a5449584de4acd8be53fefaf2] [main_8cpp_af29ec1ae9c2baac59d467be4d379f21e] [main_8cpp_abd94ded7cb6d0d29c553f52d2d926623] [main_8cpp_a1694170037849281e4db8c84dacc83ce] [main_8cpp_a2a9f405177eabe05143b129a3382e406] [main_8cpp_a57e5a12456f314ffc728d5d8da312970] [main_8cpp_a92459f6ff687f04fceaed1971c63fe89] [main_8cpp_af9b56b61a692a17c47d1e55b43b28320] [main_8cpp_a05067f85fb2548dbd7f1ba726256d60d] [main_8cpp_a4acff8232e4aec9cd5c6dc200ac55ef3] [main_8cpp_a6592d52d34d039c367f711900f17fdf7] [main_8cpp_acbd9a866ed8a9b963fee4f52d8fc9d48] [main_8cpp_a1e3954fef6954d324a4cea5118be77e9] [main_8cpp_a7dba94b79a26ddcc7a47f1b1fd880353] [main_8cpp_a28071e06a55fb35b53807b2292d77dac] [main_8cpp_a7bc6234247b5d8ec59319cb33b47b719] [main_8cpp_af6a35d8bda2bbb2656b29287230d8c81] [main_8cpp_ae7734f26f6b6e0008fe2b7884b2d4ac4] [main_8cpp_a0a07a521d3525b9b7dc70c0a625adea0] [main_8cpp_a89f234133d3efe315836311cbf21c64b] [main_8cpp_a4599153a1fb61e7bcdca1b8ea7aac88a] [main_8cpp_a3caf00a2855215688b02988d68d8b710] These funtions initiaize controllers and do the actual controller calculation. <span>#include ‘&quot;motor_controller.h‘&quot;</span> <span>#include <math><</math>iostream<math>></math></span> <span>#include <math><</math>cstring<math>></math></span> <span>#include ‘&quot;ai.h‘&quot;</span> <span>#include ‘&quot;configuration.h‘&quot;</span> <span>#include ‘&quot;korebot.h‘&quot;</span> <span>#include ‘&quot;localization_system.h‘&quot;</span> <span>#include ‘&quot;Network/tcp_connection.h‘&quot;</span> <span>#include ‘&quot;Network/network_bitstream.h‘&quot;</span> <span>#include ‘&quot;Network/packets/motor_control_speed.h‘&quot;</span> <span>#include ‘&quot;Network/packets/motor_control_manual.h‘&quot;</span> <span>#include ‘&quot;Network/packets/configuration_packet.h‘&quot;</span> <span>#include ‘&quot;DMCCom.h‘&quot;</span> <span>#include ‘&quot;INCLUDE5.H‘&quot;</span> <span>#include ‘&quot;IO5.H‘&quot;</span> === Functions === <span>'''State Model'''</span> ''[_amgrpc4df07eb6e37e6b16df68627217435d1] Calculate a state controller.'' Calculates a controller using code autogenerate from a MATLAB conroller. <span>Parameters</span> The vector input to the controller asa double is the location where the output is stored void (const double u13, double y13) <span>'''State Model Full Initialization'''</span> ''[_amgrp90df6d656fcc497e551f2b80226e3ae7] Initialize the state controller.'' Initializes a controller using code autogenerate from a MATLAB conroller. void (void) <span>'''State Model Terminalte'''</span> ''[_amgrpb57c89198c125d8a20eaf14eda168e0d] Terminalte the state controller.'' Terminates a controller using code autogenerate from a MATLAB conroller. void (void) === State Space Controlelr Configuration ‘&quot;Dance‘&quot; === Initializes a state space controller. This function initializes as state space controller (H2) that has states for the quadrotor motors and causes the system to ‘&quot;Dance‘&quot;. 1 when the initialization is complete static double 13 static void (void) === Detailed Description === These funtions initiaize controllers and do the actual controller calculation. <span>Author</span> Dylan Gransee, Robert Larsen, Paul Uhing, Ian McInerney <span>Date</span> July, 2016 These functions interact with actuators. This includes the actual controller calcuations, controller initialization, and sending the actuator commands to the FPGA. The namespace contains the data structures thqat store mast of the system’s data. Compiler macros are used to define a few modified calcuations. ssDrop defines a version the packet drop controller. posRamp defines the PIDs for the wheel velocity controllers so they are really postion controllers. LQI_strong defines a different LQI controller. ssMotors defines the H2 controller that makes the system ‘&quot;dance.‘&quot; ssTracking deines the H2 controlelr that will track reference inputs. === Function Documentation === [motor__controller_8cpp_a9ece9d0ee8318af42d3ea6a39c04438f] [motor__controller_8cpp_a50f56ed304c94c72900834bfee6880fb] [motor__controller_8cpp_ae0feaa1d69224c3c692ea4d015bf6772] [motor__controller_8cpp_aff2689042e650760bf8c24c25f98b459] === Variable Documentation === [motor__controller_8cpp_ad79f130e5c463fb8299547a7e40d3273] <span>#include <math><</math>sstream<math>></math></span> <span>#include ‘&quot;motor_controller_common.h‘&quot;</span> <span>#include ‘&quot;Network/packets/motor_control.h‘&quot;</span> <span>#include <math><</math>stddef.h<math>></math></span> <span>#include <math><</math>stdlib.h<math>></math></span> <span>#include <math><</math>string.h<math>></math></span> === Classes === class === Defines === #define  0.01 #define  -500 #define  500 === Functions === void (const double u13, double y13) void (void) void (void) === Define Documentation === [motor__controller_8h_a6f7e745f759b3e4035d8465798a4e075] [motor__controller_8h_a4d585ad2fa2a686567fe72cd14428dde] [motor__controller_8h_ac32e7bee9d8c1ee37bfae3e48852535d] === Function Documentation === [motor__controller_8h_a9ece9d0ee8318af42d3ea6a39c04438f] [motor__controller_8h_ae0feaa1d69224c3c692ea4d015bf6772] [motor__controller_8h_aff2689042e650760bf8c24c25f98b459] <span>#include ‘&quot;RADA_est.h‘&quot;</span> <span>#include ‘&quot;RADA_split_LQG1.h‘&quot;</span> <span>#include ‘&quot;RADA_LQG_s2.h‘&quot;</span> <span>#include ‘&quot;packLoss0.h‘&quot;</span> === Classes === struct struct struct struct struct struct struct struct struct struct struct struct struct struct struct struct === Defines === #define  10 #define  5 #define  5 #define  13 #define  13 #define  13 #define  5 #define  8 #define  5 #define  8 === Variables === const int = 40 static const double 513 === Define Documentation === [motor__controller__common_8h_a955a986a03f5aeb6bf10e71895a3fdc3] [motor__controller__common_8h_a01d92c67268fde027859c170514a4302] [motor__controller__common_8h_a26fc6745fdc4de3ad2ee421fc25aad41] [motor__controller__common_8h_a517216260e9c5807ff1d17e6b6ccfeff] [motor__controller__common_8h_acab00577a38703b3785f3d2310227a83] [motor__controller__common_8h_aa5b8ec5acecfe7e95912d6b3d6f64bcd] [motor__controller__common_8h_a65bdc185b18744aeb24c1ed6b3f070ea] [motor__controller__common_8h_a145ce8a02c1957fca71b9e2e241b15b4] [motor__controller__common_8h_a16dd14f45595e42913f1ef8e51127484] [motor__controller__common_8h_af1ee1bb5f099e72114ef336dae59ef7c] === Variable Documentation === [motor__controller__common_8h_af72d10797fe016402e0f6b4784fb5f72] <span>'''Initial value:'''</span> <span><span>89246, -1435, 0, 33, 2065, 26120, -420, 0, -78669, 1265, 0, 532, 33092</span>, <span>1435, 89246, 0, -2065, 33, 420, 26120, 0, -1265, -78669, 0, -33092, 53 2</span>, <span>0, 0, 34251, 0, 0, 0, 0, 1848, 0, 0, -43274, 0, 0</span>, <span>0, 10700, 0, 133545, 0, 0, -1685, 0, 0, 4740, 0, -802320, 0</span>, <span>-10700, 0, 0, 0, 133545, 1685, 0, 0, -4740, 0, 0, 0, -802320</span></span> [motor__controller__common_8h_a3bf73988242d507676faf5e730c51951] These are utility funtions. <span>#include ‘&quot;utils.h‘&quot;</span> <span>#include <math><</math>cmath<math>></math></span> <span>#include <math><</math>cstdio<math>></math></span> <span>#include <math><</math>iostream<math>></math></span> <span>#include <math><</math>termios.h<math>></math></span> === Functions === <span>'''Normalize Number'''</span> ''[_amgrp7182c311916e84625d4f869ea77768f4] Normalizes number from one range to another'' Normalizes a number within range A and B to be equivalent in range C to D <span>Parameters</span> is the number to be normaized is the minimum value of the range of the input is the maximum value of the range of the input is the minimum value of the range of the output is the maximum value of th erange of the output <span>Returns</span> the new value normaized in in the new range as a double double (double num, int A, int B, int C, int D) <span>'''Radians to Dergrees'''</span> ''[_amgrpb9794915799365dc1c3fa4144041f823] Converts a radians to degrees.'' Radians to degrees convertion utility function <span>Parameters</span> is the angle in radians to be converted as a double <span>Returns</span> the inital angle converted to degrees as a double double (double angle) <span>'''Get character'''</span> ''[_amgrp330971785c699ebf40c4e9e8bcc083e9] Gets the keyboard comands from the user.'' Gets the key board commands from the user. This works with the user interface and must be blocking as it has its own thread. the charater pressed on the user’s keyboard char () === Detailed Description === These are utility funtions. <span>Author</span> Dylan Gransee, Robert Larsen <span>Date</span> July, 2016 These utility functions can be used to normalize data, convert angle units and get input from a keyboard. === Function Documentation === [utils_8cpp_af3facad10e05defa48d45b46eb9ebe7e] [utils_8cpp_a3c082bb8a8bc92f9531055f7dd87f29e] [utils_8cpp_a45cf2c44832d15363ce9ea6ecb67a6ba] === Functions === double (double num, int A, int B, int C, int D) double (double angle) char () === Function Documentation === [utils_8h_af3facad10e05defa48d45b46eb9ebe7e] [utils_8h_a3c082bb8a8bc92f9531055f7dd87f29e] [utils_8h_a45cf2c44832d15363ce9ea6ecb67a6ba] These funtions interact with the VRPN library. <span>#include ‘&quot;vrpn.h‘&quot;</span> <span>#include <math><</math>unistd.h<math>></math></span> === Functions === <span>'''Initialize VRPN'''</span> ''[_amgrp20a78012704698ef784ff27869f78644] This funtion initializes the VRPN client that receives information about the UAV (pendulum) and trackables.'' This funtion intilialises the VRPN link with the camera system using the defined IP address to listen for data from and what port to listen at. This initializes the trackable C++ object for the two camrea system constenlation this system needs to look for. void (std::string connectionName, void(<math>\ast</math>callback)(void <math>\ast</math>, const vrpn_TRACKERCB), void(<math>\ast</math>callback1)(void <math>\ast</math>, const vrpn_TRACKERCB)) <span>'''VRPN Go Process Trackables'''</span> ''[_amgrpecbaa586fe612dd88809d85ebee6a568] This loop continously checks for new trackable data then processes it using the VRPN library.'' This function loops forever chencking the VRPN connection for new data then processing the trackable data when it recives new trackable data for constellations it is listening for. void () === Variables === vrpn_Connection <math>\ast</math> vrpn_Tracker_Remote <math>\ast</math> vrpn_Tracker_Remote <math>\ast</math> === Detailed Description === These funtions interact with the VRPN library. <span>Author</span> Dylan Gransee, Robert Larsen, Paul Uhing <span>Date</span> July, 2016 These funtions are used to interact with the VRPN data being broadcast by the camera system. === Function Documentation === [vrpn_8cpp_aad572d3b2e50ca74bc1cbb7095bb10e6] [vrpn_8cpp_aa23c89cec3a84dfd2217574495042ed1] === Variable Documentation === [vrpn_8cpp_a82358f6a74652dcb4c021fcaf08132b0] [vrpn_8cpp_aafcf6a4836ee8542ec8b2e8bcecebd2e] [vrpn_8cpp_a1808fc275087d0affb46825e96f5f7ed] <span>#include ‘&quot;vrpn_Connection.h‘&quot;</span> <span>#include ‘&quot;vrpn_Tracker.h‘&quot;</span> === Classes === struct === Functions === void (std::string connectionName, void(<math>\ast</math>)(void <math>\ast</math>, const vrpn_TRACKERCB), void(<math>\ast</math>callback1)(void <math>\ast</math>, const vrpn_TRACKERCB)) void () === Variables === static const std::string = ‘&quot;192.168.0.196‘&quot; static const int = 60560 static const int = 8 === Function Documentation === [vrpn_8h_aad572d3b2e50ca74bc1cbb7095bb10e6] [vrpn_8h_ac6e5e1f9755d0d510c997af6ee86c2c9] === Variable Documentation === [vrpn_8h_a352f55c57b6223930012cfd93bc03485] [vrpn_8h_a2cbd02aedf20e63c4a0be4c28afc976d] [vrpn_8h_a24ee7d8017cbda77544b28c99880eca1] 30c40c62a99df5b23d6e4af2bf53b26bb0a3a000 282 281 2016-08-04T19:35:01Z Pfuhing 5 Replacing page with 'test' wikitext text/x-wiki test a94a8fe5ccb19ba61c4c0873d391e987982fbbd3 File:HandModeTimingFigure.JPG 6 70 300 238 2016-08-27T17:59:02Z Jnoronha 3 Jnoronha uploaded a new version of [[File:HandModeTimingFigure.JPG]] wikitext text/x-wiki Hand Mode timing plot produced by the matlab logfile parser ebaca8b8857776b9ef950bf6d7cdf786cbbf37f1 File:HandModeTimingFigure.JPG 6 70 301 300 2016-08-27T17:59:52Z Jnoronha 3 Jnoronha uploaded a new version of [[File:HandModeTimingFigure.JPG]] wikitext text/x-wiki Hand Mode timing plot produced by the matlab logfile parser ebaca8b8857776b9ef950bf6d7cdf786cbbf37f1 File:HandModePlot.jpg 6 69 302 237 2016-08-27T18:00:24Z Jnoronha 3 Jnoronha uploaded a new version of [[File:HandModePlot.jpg]] wikitext text/x-wiki Hand Mode demo plot produced by the matlab logfile parser b68031a6bf9dcc7b0a69a5763515d6025eda6087 File:YPositionPlot.png 6 68 303 236 2016-08-27T18:00:54Z Jnoronha 3 Jnoronha uploaded a new version of [[File:YPositionPlot.png]] wikitext text/x-wiki Y position plot produced by the matlab logfile parser 0cbfa9ce48512c39aeee38c0b9d34ec8a20e813d File:XPositionPlot.png 6 67 304 235 2016-08-27T18:01:33Z Jnoronha 3 Jnoronha uploaded a new version of [[File:XPositionPlot.png]] wikitext text/x-wiki X position plot produced by the matlab logfile parser e330d18c0d830813b11e4a5551b13d1e20d2a2e5 File:TrackingToolsCrazyflieConstellationParams.png 6 45 305 147 2016-08-27T18:02:12Z Jnoronha 3 Jnoronha uploaded a new version of [[File:TrackingToolsCrazyflieConstellationParams.png]] wikitext text/x-wiki Camera System Software with Crazyflie and Hand Constellations and Server Port Info 432e585d1f7446ecf7d98fcc6976aaeedbcd9b9e File:TrackingToolsCrazyflieConstellationZeroing.png 6 43 306 145 2016-08-27T18:02:33Z Jnoronha 3 Jnoronha uploaded a new version of [[File:TrackingToolsCrazyflieConstellationZeroing.png]] wikitext text/x-wiki Camera System Software with Crazyflie and Hand Constellations loaded b20b4b16a3427dc104687a0ec094c2df21a8b1d5 File:CrazyflieTerminalRadioDriverNotDeleted.png 6 38 307 93 2016-08-27T18:03:06Z Jnoronha 3 Jnoronha uploaded a new version of [[File:CrazyflieTerminalRadioDriverNotDeleted.png]] wikitext text/x-wiki Crazyflie Terminal showing Error if Radio Driver was not properly deleted. (Unplug and Re-plug Radio Dongle) d0b2014bc578e0e9c5b8c64f7855eaf84ab407a5 File:CrazyflieTerminalNoRadio.png 6 37 308 92 2016-08-27T18:03:29Z Jnoronha 3 Jnoronha uploaded a new version of [[File:CrazyflieTerminalNoRadio.png]] wikitext text/x-wiki Crazyflie Terminal showing Error Garbage if no Radio plugged in. b33575b3a31b2001e05e2cd3f58ccb1118990e3b File:CrazyflieTerminalKeyboardInput.png 6 36 309 91 2016-08-27T18:03:53Z Jnoronha 3 Jnoronha uploaded a new version of [[File:CrazyflieTerminalKeyboardInput.png]] wikitext text/x-wiki Crazyflie Terminal showing Swarm Client after keyboard input has been pressed b1a82197fcc216cdc42515cc3ec6fff3bda23b0d File:CrazyflieTerminalProgramStarted.png 6 35 310 90 2016-08-27T18:04:23Z Jnoronha 3 Jnoronha uploaded a new version of [[File:CrazyflieTerminalProgramStarted.png]] wikitext text/x-wiki Crazyflie Terminal showing Swarm Client ready for keyboard input 17a5d428fc8c01f3bab6f28028b083544f9dcd8d File:CrazyflieTerminalRunProgram.png 6 34 311 89 2016-08-27T18:05:25Z Jnoronha 3 Jnoronha uploaded a new version of [[File:CrazyflieTerminalRunProgram.png]] wikitext text/x-wiki Crazyflie Terminal showing the run .exe command 9d78db40abd506e403e8e7da4dae4fc9c9fdf42a File:CrazyflieTerminalPostMake.png 6 32 312 87 2016-08-27T18:06:12Z Jnoronha 3 Jnoronha uploaded a new version of [[File:CrazyflieTerminalPostMake.png]] wikitext text/x-wiki Crazyflie Terminal showing an error free make build d6cea0bf6c7a21708537aa1d95eead63570705c8 File:CrazyflieTerminalInitial.png 6 31 313 86 2016-08-27T18:06:31Z Jnoronha 3 Jnoronha uploaded a new version of [[File:CrazyflieTerminalInitial.png]] wikitext text/x-wiki Crazyflie Terminal showing the make command c6f990d31f07dfcf8d93d9f828ea053eeb121328 File:DefaultCrazyflieGUIParametersScreen.JPG 6 29 314 77 2016-08-27T18:07:18Z Jnoronha 3 Jnoronha uploaded a new version of [[File:DefaultCrazyflieGUIParametersScreen.JPG]] wikitext text/x-wiki Screenshot of the Crazyflie GUI Parameters Tab ef7255336a61589fd230dbc1017eae357b6ae0be File:DefaultCrazyflieGUILoggerScreen.JPG 6 28 315 76 2016-08-27T18:07:41Z Jnoronha 3 Jnoronha uploaded a new version of [[File:DefaultCrazyflieGUILoggerScreen.JPG]] wikitext text/x-wiki Screenshot of the Crazyflie GUI logging output 8fb3c169c5958e65b424b65fa95db06f05872b2e File:DefaultCrazyflieGUIConnectScreen.JPG 6 27 316 75 2016-08-27T18:08:09Z Jnoronha 3 Jnoronha uploaded a new version of [[File:DefaultCrazyflieGUIConnectScreen.JPG]] wikitext text/x-wiki Screenshot of the Crazyflie GUI connect to radio window. 4c03f28f200c96bb4f336f5e667304c98f3b4037 Crazyflie Swarm 0 2 317 268 2016-08-27T18:15:41Z Jnoronha 3 /* Bitcraze Wiki */ added link in description too wikitext text/x-wiki The Crazyflie Swarm is a Networked Control platform designed for students to learn more about control and for researchers that wish to apply their research in practice. Platform development was started during the Summer of 2015 and continues to this day. Here you will find descriptions on how the platform works, how you can use it, and how you can get involved in developing the platform further! == Frequently Asked Questions == For help with common problems and troubleshooting please see the [[FAQ]]. == Background == The Crazyflie Swarm platform is based off of the ''Crazyflie'' Nano-quadcopter produced and maintained by [https://www.bitcraze.io/ Bitcraze]. The ''Crazyflie'' is completely open-source so we are able to look at and modify any part of the code and customize it to our needs. === Major Platform Components: === [[Image: High_Level_Figure_(Single_Radio_Single_Crazyflie_NO_NUMBERS_CROPPED).jpg‎|thumb|right|A high level overview of the Crazyflie Platform]] *[[PC Client Software]] *[[Firmware]] *[[USB Radio]] == Modifying the Platform == [[Image:SingleRadioMultiCrazyflie.jpg|thumb|right|A high level overview of the Swarm Platform we created]] *[[Controller]] *[[Logging]] *[[Keyboard Commands]] *[[USB Radio#Changing Radio Channel|Changing Radio Channel]] *[[Flight Modes]] *[[Callbacks]] *[[Adding a Crazyflie]] *[[:Firmware]] ==Future Project Ideas== The whole concept of this Platform is to constantly expand its capabilities. If you are interested in developing this platform further here are some ideas to get you started! Additional details on any of these ideas can be found on the '''[[Future Project Ideas]]''' page. *[[:Future Project Ideas#Migrating Swarm Client PID's to Firmware|Migrating Swarm Client PID's to Firmware]] *[[:Future Project Ideas#Model Development/Verification and Tuning X, Y, and Z Location PID's|Model Development/Verification and Tuning X, Y, and Z Location PID's]] *[[:Future Project Ideas#Adding Parameter Support to Swarm Client|Adding Parameter Support to Swarm Client]] *[[:Future Project Ideas#Threading Each USB Radio to speed up Computation|Threading Each USB Radio to speed up Computation]] *[[:Future Project Ideas#Developing New Controllers for the Crazyflie (pending Model Development)|Developing New Controllers for the Crazyflie (pending Model Development)]] *[[:Future Project Ideas#Develop Communications Network Between Crazyflies|Develop Communications Network Between Crazyflies]] *[[:Future Project Ideas#Trilateration Position Estimation using a Swarm|Trilateration Position Estimation using a Swarm]] == [https://wiki.bitcraze.io/ Bitcraze Wiki] == Bitcraze maintains their own wiki on the many Crazyflie systems. If you can't find what you are looking for [https://wiki.bitcraze.io/ here], chances are they will have something to help. 8ebd85d0e68e5c5143f082e528f0e184413a3bed Data Collection and Simulation Comparison 0 50 318 260 2016-08-27T22:02:54Z Jkgrund 4 /* Charging batteries */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. The initial setup and how to test the system can also be applied to demoing RADA. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA to get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supplu because it is the only power supply that we have that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} While the YouTube video linked above should explain how to use the charger. Currently three different Lithium polymer batteries (Lipo): 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery gets run really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAr 4-cell generally charge in 10-20 minutes apiece while I generally fine it takes the 2600 mAh 2-cell up to 70 minutes to charge fully. === Setting up the camera system === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password which is not posted here for security reasons but any one who works in the lab should know it. Once logged in look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should be named like ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by data modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in main project scree arrange themselves like out camera configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another pop up window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They are named like ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackless are open the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One Named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't it is the side opposite of the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system and seeing if you can use the pole to block mounting bolts of the front propeller motor mount when looking at the pole while facing the east wall. 4. While holding the pendulum approximately vertical see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and with in a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directs and hold it there. - With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation button'' - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to ''File->Save Trakables...'' and save a file using the same naming conventions as the trackable file you opened earlier except use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packed drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have fond that even on a good strt the ''[ok]'' messages will still print. === Turing on RADA === Turing on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the swiches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you only the WIFI adapter or Ethernet plugged in at the same time or VRPN my listen to the camera data broadcast over both connects which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup with out needing to close the connection. If you are using a WIFI connect use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connaction use the command ''ssh root@192.168.0.54''. If the connection goes though you should be proped for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the first test after power up === For the firs test after powering on Eris a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect the the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell scrip will setup the NFS, load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject and runs the executable. Once the user exits the executable the log file produces is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see an warning that when coping the log file Eris couldn't maintain the file permisiion settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This Date stamp uses date on Eris which is currently in June of 2008 as of August 2nd, 2016. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA, you will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after start up you don't need to run this script. See the Section about Running additional tests below. [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode you can use the following commands to enter the desired mode with a three second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode, this will only really work when using PIDs to control the pendulum. -''b'' : Enter Robot control mode, in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode, where the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file incase odd things happen somewhere. This just increments a counter so if you use it look for changes in the marker value. ==== Robot Control Model ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box set mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use he same commands as Tuning Mode. === Running additional Tests === Once you have run one test with Eris on it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_stat_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result it is ready to test much quicker. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and retrieving log files === If you are only demoing the system there is no need to go beyond this point. Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files are named like ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful of describing what the test was of or for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring battery voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there isn't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log is the headder. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value latter. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== 1. After test disconnect wheel battery from the system. 2. Measure voltage of battery using multimeter. [[Image:MeasureVwheel.jpg|800px]] You can use the plug used for charging the 2-cell Lipos but make sure to connect the plug to the multimeter before connecting the battery and disconnect the battery before disconnecting the plug from the mulitmeter. It is generally the best practice to give the multimeter a few minutes to allow for the voltage measurement to stabilize as the battery measurement tends to be a little low right after the test. The multimeter will report data out to four decimal places it is best just to round to three decimal places for the wheel voltage. ==== Quad Battery ==== 1. Setup code to run all four propellers at 50% throttle, uncomment the definition of ''mot50'' in main.cpp and compile the project. 2. Power off propellers by turning off the switch to the ESCs. 3. Connect multimeter to measure the voltage across one of the ESCs. This is done by using the power splitter cord. -Connect one of the female XT60 connectors on the splitter to a male XT60 connector to banana connector cable. -The banana connector connect to the hand held multimeter. The multimeter should be set to the 20VDC measurement setting. -Next unplug one the ESCs' power connection. -reconnect the ESC to power through the two remain connectors on the spliter cable. 4. Power on the propellers. 5. Run the system at 50% throttle and measure the steady-state voltage during the test. The battery will slow the voltage decay significantly, meaning it will keep the same measurement for a few seconds. 6. Stop the test and record the voltage in the log file. Make sure to disconnect the batter before removing the splitter cable. {| class="wikitable" style="text-align:center" |- | [[Image:PowerSplitter.jpg|200px]] | [[Image:QuadMultiCon.jpg |200px]] | [[Image:QuadMultiSet.JPG |200px]] | [[Image:QuadMeasESCcon.JPG|200px]] |- | Splitter cord. | Connect splitter to multimeter. | Settings for multimeter. | Connecting ESC through splitter. |} The testing setup should look like the image below: [[Image:QuadBattMeas.jpg|800px]] == Post processing and Simulation == Simulating a test of RADA starts with processing and storing the data. Then all of the parameters of the model are loaded in the MATLAB Workspace. Finally the Simulink file used for the simulation is opened and the length of the simulation is set to match the length of the actual test. The simulation is run and the simulation output is stored. Finally the data should be plotted and compared. === Using the MATLAB data parsing tool === In depth discussion of how to use the log file parsing tool is described [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] I suggest using the version of the tool in the rada_resarch_project git repository Paul Uhing used for his Master's research. It con be found on CO3050-11 under the ucart account in the directory ''~/rada_research_project/DataAnalysiTool_omnicoor/Tool''. Simply open MATLAB and set the working directory to this file path. In the MATLAB Command Prompt run ''DataAnalysis''. A popup window should open up. Select the log file you want to process and wait for the tool to finish processing the file. Once this is complete there should be four structures in the MATLAB workspace. -'''main''' : This contains all of the data extracted from the log file and the processing parameters used. main.expData contains two time structures: Time is used for the pendulum data and Eris_time is used for the ground vehicle data. -'''X_ref''' : This contains the reference vector in m/s for x velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Y_ref''' : This contains the reference vector in m/s for y velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Yaw_ref''' : This contains the reference vector in radians for yaw that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. This one is new incase people start testing the system with heading changes but is not used in the current setup. The first thing you should do is rename the main structure to the name you used for the log file. This is helpful for comparing multiple tests. Next you will want to crate two new variable ''Vquad_test'' an Vw_test''. In the MATLAB Command Prompt set the measured propeller voltage from the log file to ''Vquad_test'' and set the measured the wheel voltage to ''Vw_test'' as this will be used by the simulation. Finally if you did an open-loop test of the wheels create the variable ''Uol'' and set it to the open-loop wheel command used. Save all of these variables from the MATLAB workspace to a ''.mat'' file of the same name as log file you extracted the data from and save it in the same directory as your RADA Simulink files. As of August 2nd, 2016 this directory is ''~/rada_research_project/MATLAB/RADA.'' === Setting up the MATLAB workspace for simulation === Change your MATLAB directory to this directory. Then run the simulation setup files. Currently you just need to run ''modelParams_smallWheels_RADA'' in the MATLAB Command Prompt. Next open the Simulink file with that contains the model of RADA controlled by the controller you tested. -'''RADA_psiCtrl_v2_lqi_est.slx''' contains LQI, LQI+estimation, and LQG controller simulations. -'''RADA_psiCtrl_v2.slx''' contains the PID controlled system. -'''RADA_psiCtrl_v2_LQGsep.slx''' contains the subsystem LQG controlled system. -'''RADA_psiCtrl_v2_LQGsep_ol.slx''' contains the simulation of the pendulum system controlled by an LQG and Eris controlled with open-loop commands. Note all of the current (August 2nd, 2016) ''.slx'' files were created in MATLAB 2014b and will only work in MATLAB 2014B or newer. Then in the MATLAB Command Prompt type ''X_ref.time(end)'' exactly, don't add a semicolon, and hit enter. MATLAB will print the time of the last command in the X_ref structure. Set the en time of the simulation to this value and save your Simulink file. === Running simulations and storing results === Before running the simulation make sure that the simuation is using the ''ode23t'' differential equations solver. This system is a moderately stiff system of differential and the ''ode45'' solver doesn't do well with these types of systems. When using ''ode23t'' is should only take a few minutes to run a 100+ second simulation while doing the same test using ''ode45'' could take 8 hours. While this slow it is also bad for your hard drive as the simulation has to page between RAM and your computers hard drive a lot. Once this check is done run the simulation. While it is running check what the output structures variables are named for for your RADA test system. Once the simulation is done go to your MATLAB Workspace and select all 15 outputs for your simulation or your sub-simulation if you used '''RADA_psiCtrl_v2_lqi_est.slx'''. Save these 15 output structures to a ''.mat'' file named as the log file with _sim appended to the end of the name. The 15 outputs are structures containing a time vector and then the data from the simulation sampled at 100 Hz and the units of this data are the SI units (ex: radians, m/s). There is one output structure for x velocity, y velocity, x body velocity, y body velocity, theta (pitch), phi (roll), psi (yaw), and one per actuator command (ex: the command sent to a wheel). Now you have all the data you can plot it. === Plotting results === If you look at the ''DataSets'' folder below ''~/rada_research_project/MATLAB/RADA'' directory there are plenty of examples of how Paul Uhing compared simulation to test data. Generally you should grate a ''.m'' file with the same name as the log file this data was extracted from with _plot appended to the name. Generally you can just copy an for RADA_LQG_compPID_plot.m RADA_PID_compLQG_plot.m, RADA_LQG_sep_plot.m, or RADA_LQG_sep_ol_plot.m files and rename the structures for your test. These files create four figures. Figure 1 plots compares the x velocity data in the first sub figure and compares pitch (theta) data in the second sub figure. Figure 2 does the same thing as Figure 1 but with y velocity and roll data. Figure 3 looks at the yaw data. Finally, Figure 4 looks at the sample period between UAV and ERIS packets from the camera system just to check for periods of time with large packet drops. You can follow a similar pattern to compare motor commands. Just make sure that you compare Quad Motor 2 from the test data with Quad Motor 4 from simulation and vise versa because propellers 2 and 4 were switch in Eris's software compared to the Model. That is all you need to know for testing RADA against the model. a84e4b6da08525c8302bcc04053dba14227adf92 328 318 2016-09-21T14:33:07Z Jonessk 7 /* Setting Up a RADA Test */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. The initial setup and how to test the system can also be applied to demoing RADA. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supply because it is the only power supply that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} The YouTube video link above should explain how to use the charger. RADA currently uses three different Lithium polymer (Lipo) batteries: 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo for the propellers. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery voltage drops really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAh 4-cell generally charge in 10-20 minutes apiece while the 2600 mAh 2-cell generally take up to 70 minutes to charge fully. === Setting up the Camera System === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password (not posted here for security reasons, but any one who works in the lab should know it). Once logged in, look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should have the naming scheme ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by date modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in the main project screen arrange themselves like the camera system configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another popup window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They have the naming scheme ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackables are open, the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation, left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't, the front is the side opposite the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system. If the system is aligned, you should be able to block the mounting bolts of the front propeller motor with the pole while facing the east wall. 4. While holding the pendulum approximately vertical, see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and within a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise, go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directions and hold it there. - With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation button'' - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to ''File->Save Trackables...'' and save a file using the same naming conventions as the trackable file you opened earlier. Use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packed drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have fond that even on a good strt the ''[ok]'' messages will still print. === Turing on RADA === Turing on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the swiches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you only the WIFI adapter or Ethernet plugged in at the same time or VRPN my listen to the camera data broadcast over both connects which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup with out needing to close the connection. If you are using a WIFI connect use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connaction use the command ''ssh root@192.168.0.54''. If the connection goes though you should be proped for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the first test after power up === For the firs test after powering on Eris a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect the the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell scrip will setup the NFS, load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject and runs the executable. Once the user exits the executable the log file produces is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see an warning that when coping the log file Eris couldn't maintain the file permisiion settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This Date stamp uses date on Eris which is currently in June of 2008 as of August 2nd, 2016. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA, you will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after start up you don't need to run this script. See the Section about Running additional tests below. [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode you can use the following commands to enter the desired mode with a three second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode, this will only really work when using PIDs to control the pendulum. -''b'' : Enter Robot control mode, in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode, where the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file incase odd things happen somewhere. This just increments a counter so if you use it look for changes in the marker value. ==== Robot Control Model ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box set mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use he same commands as Tuning Mode. === Running additional Tests === Once you have run one test with Eris on it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_stat_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result it is ready to test much quicker. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and retrieving log files === If you are only demoing the system there is no need to go beyond this point. Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files are named like ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful of describing what the test was of or for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring battery voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there isn't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log is the headder. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value latter. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== 1. After test disconnect wheel battery from the system. 2. Measure voltage of battery using multimeter. [[Image:MeasureVwheel.jpg|800px]] You can use the plug used for charging the 2-cell Lipos but make sure to connect the plug to the multimeter before connecting the battery and disconnect the battery before disconnecting the plug from the mulitmeter. It is generally the best practice to give the multimeter a few minutes to allow for the voltage measurement to stabilize as the battery measurement tends to be a little low right after the test. The multimeter will report data out to four decimal places it is best just to round to three decimal places for the wheel voltage. ==== Quad Battery ==== 1. Setup code to run all four propellers at 50% throttle, uncomment the definition of ''mot50'' in main.cpp and compile the project. 2. Power off propellers by turning off the switch to the ESCs. 3. Connect multimeter to measure the voltage across one of the ESCs. This is done by using the power splitter cord. -Connect one of the female XT60 connectors on the splitter to a male XT60 connector to banana connector cable. -The banana connector connect to the hand held multimeter. The multimeter should be set to the 20VDC measurement setting. -Next unplug one the ESCs' power connection. -reconnect the ESC to power through the two remain connectors on the spliter cable. 4. Power on the propellers. 5. Run the system at 50% throttle and measure the steady-state voltage during the test. The battery will slow the voltage decay significantly, meaning it will keep the same measurement for a few seconds. 6. Stop the test and record the voltage in the log file. Make sure to disconnect the batter before removing the splitter cable. {| class="wikitable" style="text-align:center" |- | [[Image:PowerSplitter.jpg|200px]] | [[Image:QuadMultiCon.jpg |200px]] | [[Image:QuadMultiSet.JPG |200px]] | [[Image:QuadMeasESCcon.JPG|200px]] |- | Splitter cord. | Connect splitter to multimeter. | Settings for multimeter. | Connecting ESC through splitter. |} The testing setup should look like the image below: [[Image:QuadBattMeas.jpg|800px]] == Post processing and Simulation == Simulating a test of RADA starts with processing and storing the data. Then all of the parameters of the model are loaded in the MATLAB Workspace. Finally the Simulink file used for the simulation is opened and the length of the simulation is set to match the length of the actual test. The simulation is run and the simulation output is stored. Finally the data should be plotted and compared. === Using the MATLAB data parsing tool === In depth discussion of how to use the log file parsing tool is described [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] I suggest using the version of the tool in the rada_resarch_project git repository Paul Uhing used for his Master's research. It con be found on CO3050-11 under the ucart account in the directory ''~/rada_research_project/DataAnalysiTool_omnicoor/Tool''. Simply open MATLAB and set the working directory to this file path. In the MATLAB Command Prompt run ''DataAnalysis''. A popup window should open up. Select the log file you want to process and wait for the tool to finish processing the file. Once this is complete there should be four structures in the MATLAB workspace. -'''main''' : This contains all of the data extracted from the log file and the processing parameters used. main.expData contains two time structures: Time is used for the pendulum data and Eris_time is used for the ground vehicle data. -'''X_ref''' : This contains the reference vector in m/s for x velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Y_ref''' : This contains the reference vector in m/s for y velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Yaw_ref''' : This contains the reference vector in radians for yaw that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. This one is new incase people start testing the system with heading changes but is not used in the current setup. The first thing you should do is rename the main structure to the name you used for the log file. This is helpful for comparing multiple tests. Next you will want to crate two new variable ''Vquad_test'' an Vw_test''. In the MATLAB Command Prompt set the measured propeller voltage from the log file to ''Vquad_test'' and set the measured the wheel voltage to ''Vw_test'' as this will be used by the simulation. Finally if you did an open-loop test of the wheels create the variable ''Uol'' and set it to the open-loop wheel command used. Save all of these variables from the MATLAB workspace to a ''.mat'' file of the same name as log file you extracted the data from and save it in the same directory as your RADA Simulink files. As of August 2nd, 2016 this directory is ''~/rada_research_project/MATLAB/RADA.'' === Setting up the MATLAB workspace for simulation === Change your MATLAB directory to this directory. Then run the simulation setup files. Currently you just need to run ''modelParams_smallWheels_RADA'' in the MATLAB Command Prompt. Next open the Simulink file with that contains the model of RADA controlled by the controller you tested. -'''RADA_psiCtrl_v2_lqi_est.slx''' contains LQI, LQI+estimation, and LQG controller simulations. -'''RADA_psiCtrl_v2.slx''' contains the PID controlled system. -'''RADA_psiCtrl_v2_LQGsep.slx''' contains the subsystem LQG controlled system. -'''RADA_psiCtrl_v2_LQGsep_ol.slx''' contains the simulation of the pendulum system controlled by an LQG and Eris controlled with open-loop commands. Note all of the current (August 2nd, 2016) ''.slx'' files were created in MATLAB 2014b and will only work in MATLAB 2014B or newer. Then in the MATLAB Command Prompt type ''X_ref.time(end)'' exactly, don't add a semicolon, and hit enter. MATLAB will print the time of the last command in the X_ref structure. Set the en time of the simulation to this value and save your Simulink file. === Running simulations and storing results === Before running the simulation make sure that the simuation is using the ''ode23t'' differential equations solver. This system is a moderately stiff system of differential and the ''ode45'' solver doesn't do well with these types of systems. When using ''ode23t'' is should only take a few minutes to run a 100+ second simulation while doing the same test using ''ode45'' could take 8 hours. While this slow it is also bad for your hard drive as the simulation has to page between RAM and your computers hard drive a lot. Once this check is done run the simulation. While it is running check what the output structures variables are named for for your RADA test system. Once the simulation is done go to your MATLAB Workspace and select all 15 outputs for your simulation or your sub-simulation if you used '''RADA_psiCtrl_v2_lqi_est.slx'''. Save these 15 output structures to a ''.mat'' file named as the log file with _sim appended to the end of the name. The 15 outputs are structures containing a time vector and then the data from the simulation sampled at 100 Hz and the units of this data are the SI units (ex: radians, m/s). There is one output structure for x velocity, y velocity, x body velocity, y body velocity, theta (pitch), phi (roll), psi (yaw), and one per actuator command (ex: the command sent to a wheel). Now you have all the data you can plot it. === Plotting results === If you look at the ''DataSets'' folder below ''~/rada_research_project/MATLAB/RADA'' directory there are plenty of examples of how Paul Uhing compared simulation to test data. Generally you should grate a ''.m'' file with the same name as the log file this data was extracted from with _plot appended to the name. Generally you can just copy an for RADA_LQG_compPID_plot.m RADA_PID_compLQG_plot.m, RADA_LQG_sep_plot.m, or RADA_LQG_sep_ol_plot.m files and rename the structures for your test. These files create four figures. Figure 1 plots compares the x velocity data in the first sub figure and compares pitch (theta) data in the second sub figure. Figure 2 does the same thing as Figure 1 but with y velocity and roll data. Figure 3 looks at the yaw data. Finally, Figure 4 looks at the sample period between UAV and ERIS packets from the camera system just to check for periods of time with large packet drops. You can follow a similar pattern to compare motor commands. Just make sure that you compare Quad Motor 2 from the test data with Quad Motor 4 from simulation and vise versa because propellers 2 and 4 were switch in Eris's software compared to the Model. That is all you need to know for testing RADA against the model. 0f903b6a65b039c1b5be27d27dd33b65a1a9b087 329 328 2016-09-21T14:33:35Z Jonessk 7 /* Setting Up a RADA Test */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. The initial setup and how to test the system can also be applied to demoing RADA. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging Batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supply because it is the only power supply that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} The YouTube video link above should explain how to use the charger. RADA currently uses three different Lithium polymer (Lipo) batteries: 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo for the propellers. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery voltage drops really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAh 4-cell generally charge in 10-20 minutes apiece while the 2600 mAh 2-cell generally take up to 70 minutes to charge fully. === Setting up the Camera System === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password (not posted here for security reasons, but any one who works in the lab should know it). Once logged in, look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should have the naming scheme ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by date modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in the main project screen arrange themselves like the camera system configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another popup window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They have the naming scheme ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackables are open, the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation, left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't, the front is the side opposite the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system. If the system is aligned, you should be able to block the mounting bolts of the front propeller motor with the pole while facing the east wall. 4. While holding the pendulum approximately vertical, see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and within a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise, go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directions and hold it there. - With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation button'' - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to ''File->Save Trackables...'' and save a file using the same naming conventions as the trackable file you opened earlier. Use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use. The password isn't put here for security reasons. In order to ensure that the RADA software is setup correctly for the test you want to run. To do this you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below is a compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also cause the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propllers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by a LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to acclerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packed drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have fond that even on a good strt the ''[ok]'' messages will still print. === Turing on RADA === Turing on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the swiches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you only the WIFI adapter or Ethernet plugged in at the same time or VRPN my listen to the camera data broadcast over both connects which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup with out needing to close the connection. If you are using a WIFI connect use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connaction use the command ''ssh root@192.168.0.54''. If the connection goes though you should be proped for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the first test after power up === For the firs test after powering on Eris a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect the the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell scrip will setup the NFS, load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject and runs the executable. Once the user exits the executable the log file produces is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see an warning that when coping the log file Eris couldn't maintain the file permisiion settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This Date stamp uses date on Eris which is currently in June of 2008 as of August 2nd, 2016. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA, you will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after start up you don't need to run this script. See the Section about Running additional tests below. [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode you can use the following commands to enter the desired mode with a three second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode, this will only really work when using PIDs to control the pendulum. -''b'' : Enter Robot control mode, in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode, where the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file incase odd things happen somewhere. This just increments a counter so if you use it look for changes in the marker value. ==== Robot Control Model ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box set mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use he same commands as Tuning Mode. === Running additional Tests === Once you have run one test with Eris on it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_stat_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result it is ready to test much quicker. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and retrieving log files === If you are only demoing the system there is no need to go beyond this point. Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files are named like ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful of describing what the test was of or for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring battery voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there isn't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log is the headder. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value latter. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== 1. After test disconnect wheel battery from the system. 2. Measure voltage of battery using multimeter. [[Image:MeasureVwheel.jpg|800px]] You can use the plug used for charging the 2-cell Lipos but make sure to connect the plug to the multimeter before connecting the battery and disconnect the battery before disconnecting the plug from the mulitmeter. It is generally the best practice to give the multimeter a few minutes to allow for the voltage measurement to stabilize as the battery measurement tends to be a little low right after the test. The multimeter will report data out to four decimal places it is best just to round to three decimal places for the wheel voltage. ==== Quad Battery ==== 1. Setup code to run all four propellers at 50% throttle, uncomment the definition of ''mot50'' in main.cpp and compile the project. 2. Power off propellers by turning off the switch to the ESCs. 3. Connect multimeter to measure the voltage across one of the ESCs. This is done by using the power splitter cord. -Connect one of the female XT60 connectors on the splitter to a male XT60 connector to banana connector cable. -The banana connector connect to the hand held multimeter. The multimeter should be set to the 20VDC measurement setting. -Next unplug one the ESCs' power connection. -reconnect the ESC to power through the two remain connectors on the spliter cable. 4. Power on the propellers. 5. Run the system at 50% throttle and measure the steady-state voltage during the test. The battery will slow the voltage decay significantly, meaning it will keep the same measurement for a few seconds. 6. Stop the test and record the voltage in the log file. Make sure to disconnect the batter before removing the splitter cable. {| class="wikitable" style="text-align:center" |- | [[Image:PowerSplitter.jpg|200px]] | [[Image:QuadMultiCon.jpg |200px]] | [[Image:QuadMultiSet.JPG |200px]] | [[Image:QuadMeasESCcon.JPG|200px]] |- | Splitter cord. | Connect splitter to multimeter. | Settings for multimeter. | Connecting ESC through splitter. |} The testing setup should look like the image below: [[Image:QuadBattMeas.jpg|800px]] == Post processing and Simulation == Simulating a test of RADA starts with processing and storing the data. Then all of the parameters of the model are loaded in the MATLAB Workspace. Finally the Simulink file used for the simulation is opened and the length of the simulation is set to match the length of the actual test. The simulation is run and the simulation output is stored. Finally the data should be plotted and compared. === Using the MATLAB data parsing tool === In depth discussion of how to use the log file parsing tool is described [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] I suggest using the version of the tool in the rada_resarch_project git repository Paul Uhing used for his Master's research. It con be found on CO3050-11 under the ucart account in the directory ''~/rada_research_project/DataAnalysiTool_omnicoor/Tool''. Simply open MATLAB and set the working directory to this file path. In the MATLAB Command Prompt run ''DataAnalysis''. A popup window should open up. Select the log file you want to process and wait for the tool to finish processing the file. Once this is complete there should be four structures in the MATLAB workspace. -'''main''' : This contains all of the data extracted from the log file and the processing parameters used. main.expData contains two time structures: Time is used for the pendulum data and Eris_time is used for the ground vehicle data. -'''X_ref''' : This contains the reference vector in m/s for x velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Y_ref''' : This contains the reference vector in m/s for y velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Yaw_ref''' : This contains the reference vector in radians for yaw that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. This one is new incase people start testing the system with heading changes but is not used in the current setup. The first thing you should do is rename the main structure to the name you used for the log file. This is helpful for comparing multiple tests. Next you will want to crate two new variable ''Vquad_test'' an Vw_test''. In the MATLAB Command Prompt set the measured propeller voltage from the log file to ''Vquad_test'' and set the measured the wheel voltage to ''Vw_test'' as this will be used by the simulation. Finally if you did an open-loop test of the wheels create the variable ''Uol'' and set it to the open-loop wheel command used. Save all of these variables from the MATLAB workspace to a ''.mat'' file of the same name as log file you extracted the data from and save it in the same directory as your RADA Simulink files. As of August 2nd, 2016 this directory is ''~/rada_research_project/MATLAB/RADA.'' === Setting up the MATLAB workspace for simulation === Change your MATLAB directory to this directory. Then run the simulation setup files. Currently you just need to run ''modelParams_smallWheels_RADA'' in the MATLAB Command Prompt. Next open the Simulink file with that contains the model of RADA controlled by the controller you tested. -'''RADA_psiCtrl_v2_lqi_est.slx''' contains LQI, LQI+estimation, and LQG controller simulations. -'''RADA_psiCtrl_v2.slx''' contains the PID controlled system. -'''RADA_psiCtrl_v2_LQGsep.slx''' contains the subsystem LQG controlled system. -'''RADA_psiCtrl_v2_LQGsep_ol.slx''' contains the simulation of the pendulum system controlled by an LQG and Eris controlled with open-loop commands. Note all of the current (August 2nd, 2016) ''.slx'' files were created in MATLAB 2014b and will only work in MATLAB 2014B or newer. Then in the MATLAB Command Prompt type ''X_ref.time(end)'' exactly, don't add a semicolon, and hit enter. MATLAB will print the time of the last command in the X_ref structure. Set the en time of the simulation to this value and save your Simulink file. === Running simulations and storing results === Before running the simulation make sure that the simuation is using the ''ode23t'' differential equations solver. This system is a moderately stiff system of differential and the ''ode45'' solver doesn't do well with these types of systems. When using ''ode23t'' is should only take a few minutes to run a 100+ second simulation while doing the same test using ''ode45'' could take 8 hours. While this slow it is also bad for your hard drive as the simulation has to page between RAM and your computers hard drive a lot. Once this check is done run the simulation. While it is running check what the output structures variables are named for for your RADA test system. Once the simulation is done go to your MATLAB Workspace and select all 15 outputs for your simulation or your sub-simulation if you used '''RADA_psiCtrl_v2_lqi_est.slx'''. Save these 15 output structures to a ''.mat'' file named as the log file with _sim appended to the end of the name. The 15 outputs are structures containing a time vector and then the data from the simulation sampled at 100 Hz and the units of this data are the SI units (ex: radians, m/s). There is one output structure for x velocity, y velocity, x body velocity, y body velocity, theta (pitch), phi (roll), psi (yaw), and one per actuator command (ex: the command sent to a wheel). Now you have all the data you can plot it. === Plotting results === If you look at the ''DataSets'' folder below ''~/rada_research_project/MATLAB/RADA'' directory there are plenty of examples of how Paul Uhing compared simulation to test data. Generally you should grate a ''.m'' file with the same name as the log file this data was extracted from with _plot appended to the name. Generally you can just copy an for RADA_LQG_compPID_plot.m RADA_PID_compLQG_plot.m, RADA_LQG_sep_plot.m, or RADA_LQG_sep_ol_plot.m files and rename the structures for your test. These files create four figures. Figure 1 plots compares the x velocity data in the first sub figure and compares pitch (theta) data in the second sub figure. Figure 2 does the same thing as Figure 1 but with y velocity and roll data. Figure 3 looks at the yaw data. Finally, Figure 4 looks at the sample period between UAV and ERIS packets from the camera system just to check for periods of time with large packet drops. You can follow a similar pattern to compare motor commands. Just make sure that you compare Quad Motor 2 from the test data with Quad Motor 4 from simulation and vise versa because propellers 2 and 4 were switch in Eris's software compared to the Model. That is all you need to know for testing RADA against the model. b4b450113afaf0f1b4355715a442e39c358d8d0e 330 329 2016-09-21T14:42:24Z Jonessk 7 /* Building Software */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. The initial setup and how to test the system can also be applied to demoing RADA. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging Batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supply because it is the only power supply that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} The YouTube video link above should explain how to use the charger. RADA currently uses three different Lithium polymer (Lipo) batteries: 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo for the propellers. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery voltage drops really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAh 4-cell generally charge in 10-20 minutes apiece while the 2600 mAh 2-cell generally take up to 70 minutes to charge fully. === Setting up the Camera System === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password (not posted here for security reasons, but any one who works in the lab should know it). Once logged in, look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should have the naming scheme ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by date modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in the main project screen arrange themselves like the camera system configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another popup window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They have the naming scheme ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackables are open, the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation, left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't, the front is the side opposite the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system. If the system is aligned, you should be able to block the mounting bolts of the front propeller motor with the pole while facing the east wall. 4. While holding the pendulum approximately vertical, see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and within a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise, go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directions and hold it there. - With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation button'' - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to ''File->Save Trackables...'' and save a file using the same naming conventions as the trackable file you opened earlier. Use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use (the password isn't put here for security reasons). First, ensure that the RADA software is setup correctly for the test you want to run. To do this, you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below are compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also causes the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propellers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by an LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to accelerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packet drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA Senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have found that even on a good strt the ''[ok]'' messages will still print. === Turing on RADA === Turing on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the swiches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you only the WIFI adapter or Ethernet plugged in at the same time or VRPN my listen to the camera data broadcast over both connects which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup with out needing to close the connection. If you are using a WIFI connect use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connaction use the command ''ssh root@192.168.0.54''. If the connection goes though you should be proped for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the first test after power up === For the firs test after powering on Eris a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect the the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell scrip will setup the NFS, load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject and runs the executable. Once the user exits the executable the log file produces is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see an warning that when coping the log file Eris couldn't maintain the file permisiion settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This Date stamp uses date on Eris which is currently in June of 2008 as of August 2nd, 2016. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA, you will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after start up you don't need to run this script. See the Section about Running additional tests below. [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode you can use the following commands to enter the desired mode with a three second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode, this will only really work when using PIDs to control the pendulum. -''b'' : Enter Robot control mode, in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode, where the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file incase odd things happen somewhere. This just increments a counter so if you use it look for changes in the marker value. ==== Robot Control Model ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box set mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use he same commands as Tuning Mode. === Running additional Tests === Once you have run one test with Eris on it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_stat_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result it is ready to test much quicker. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and retrieving log files === If you are only demoing the system there is no need to go beyond this point. Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files are named like ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful of describing what the test was of or for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring battery voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there isn't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log is the headder. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value latter. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== 1. After test disconnect wheel battery from the system. 2. Measure voltage of battery using multimeter. [[Image:MeasureVwheel.jpg|800px]] You can use the plug used for charging the 2-cell Lipos but make sure to connect the plug to the multimeter before connecting the battery and disconnect the battery before disconnecting the plug from the mulitmeter. It is generally the best practice to give the multimeter a few minutes to allow for the voltage measurement to stabilize as the battery measurement tends to be a little low right after the test. The multimeter will report data out to four decimal places it is best just to round to three decimal places for the wheel voltage. ==== Quad Battery ==== 1. Setup code to run all four propellers at 50% throttle, uncomment the definition of ''mot50'' in main.cpp and compile the project. 2. Power off propellers by turning off the switch to the ESCs. 3. Connect multimeter to measure the voltage across one of the ESCs. This is done by using the power splitter cord. -Connect one of the female XT60 connectors on the splitter to a male XT60 connector to banana connector cable. -The banana connector connect to the hand held multimeter. The multimeter should be set to the 20VDC measurement setting. -Next unplug one the ESCs' power connection. -reconnect the ESC to power through the two remain connectors on the spliter cable. 4. Power on the propellers. 5. Run the system at 50% throttle and measure the steady-state voltage during the test. The battery will slow the voltage decay significantly, meaning it will keep the same measurement for a few seconds. 6. Stop the test and record the voltage in the log file. Make sure to disconnect the batter before removing the splitter cable. {| class="wikitable" style="text-align:center" |- | [[Image:PowerSplitter.jpg|200px]] | [[Image:QuadMultiCon.jpg |200px]] | [[Image:QuadMultiSet.JPG |200px]] | [[Image:QuadMeasESCcon.JPG|200px]] |- | Splitter cord. | Connect splitter to multimeter. | Settings for multimeter. | Connecting ESC through splitter. |} The testing setup should look like the image below: [[Image:QuadBattMeas.jpg|800px]] == Post processing and Simulation == Simulating a test of RADA starts with processing and storing the data. Then all of the parameters of the model are loaded in the MATLAB Workspace. Finally the Simulink file used for the simulation is opened and the length of the simulation is set to match the length of the actual test. The simulation is run and the simulation output is stored. Finally the data should be plotted and compared. === Using the MATLAB data parsing tool === In depth discussion of how to use the log file parsing tool is described [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] I suggest using the version of the tool in the rada_resarch_project git repository Paul Uhing used for his Master's research. It con be found on CO3050-11 under the ucart account in the directory ''~/rada_research_project/DataAnalysiTool_omnicoor/Tool''. Simply open MATLAB and set the working directory to this file path. In the MATLAB Command Prompt run ''DataAnalysis''. A popup window should open up. Select the log file you want to process and wait for the tool to finish processing the file. Once this is complete there should be four structures in the MATLAB workspace. -'''main''' : This contains all of the data extracted from the log file and the processing parameters used. main.expData contains two time structures: Time is used for the pendulum data and Eris_time is used for the ground vehicle data. -'''X_ref''' : This contains the reference vector in m/s for x velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Y_ref''' : This contains the reference vector in m/s for y velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Yaw_ref''' : This contains the reference vector in radians for yaw that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. This one is new incase people start testing the system with heading changes but is not used in the current setup. The first thing you should do is rename the main structure to the name you used for the log file. This is helpful for comparing multiple tests. Next you will want to crate two new variable ''Vquad_test'' an Vw_test''. In the MATLAB Command Prompt set the measured propeller voltage from the log file to ''Vquad_test'' and set the measured the wheel voltage to ''Vw_test'' as this will be used by the simulation. Finally if you did an open-loop test of the wheels create the variable ''Uol'' and set it to the open-loop wheel command used. Save all of these variables from the MATLAB workspace to a ''.mat'' file of the same name as log file you extracted the data from and save it in the same directory as your RADA Simulink files. As of August 2nd, 2016 this directory is ''~/rada_research_project/MATLAB/RADA.'' === Setting up the MATLAB workspace for simulation === Change your MATLAB directory to this directory. Then run the simulation setup files. Currently you just need to run ''modelParams_smallWheels_RADA'' in the MATLAB Command Prompt. Next open the Simulink file with that contains the model of RADA controlled by the controller you tested. -'''RADA_psiCtrl_v2_lqi_est.slx''' contains LQI, LQI+estimation, and LQG controller simulations. -'''RADA_psiCtrl_v2.slx''' contains the PID controlled system. -'''RADA_psiCtrl_v2_LQGsep.slx''' contains the subsystem LQG controlled system. -'''RADA_psiCtrl_v2_LQGsep_ol.slx''' contains the simulation of the pendulum system controlled by an LQG and Eris controlled with open-loop commands. Note all of the current (August 2nd, 2016) ''.slx'' files were created in MATLAB 2014b and will only work in MATLAB 2014B or newer. Then in the MATLAB Command Prompt type ''X_ref.time(end)'' exactly, don't add a semicolon, and hit enter. MATLAB will print the time of the last command in the X_ref structure. Set the en time of the simulation to this value and save your Simulink file. === Running simulations and storing results === Before running the simulation make sure that the simuation is using the ''ode23t'' differential equations solver. This system is a moderately stiff system of differential and the ''ode45'' solver doesn't do well with these types of systems. When using ''ode23t'' is should only take a few minutes to run a 100+ second simulation while doing the same test using ''ode45'' could take 8 hours. While this slow it is also bad for your hard drive as the simulation has to page between RAM and your computers hard drive a lot. Once this check is done run the simulation. While it is running check what the output structures variables are named for for your RADA test system. Once the simulation is done go to your MATLAB Workspace and select all 15 outputs for your simulation or your sub-simulation if you used '''RADA_psiCtrl_v2_lqi_est.slx'''. Save these 15 output structures to a ''.mat'' file named as the log file with _sim appended to the end of the name. The 15 outputs are structures containing a time vector and then the data from the simulation sampled at 100 Hz and the units of this data are the SI units (ex: radians, m/s). There is one output structure for x velocity, y velocity, x body velocity, y body velocity, theta (pitch), phi (roll), psi (yaw), and one per actuator command (ex: the command sent to a wheel). Now you have all the data you can plot it. === Plotting results === If you look at the ''DataSets'' folder below ''~/rada_research_project/MATLAB/RADA'' directory there are plenty of examples of how Paul Uhing compared simulation to test data. Generally you should grate a ''.m'' file with the same name as the log file this data was extracted from with _plot appended to the name. Generally you can just copy an for RADA_LQG_compPID_plot.m RADA_PID_compLQG_plot.m, RADA_LQG_sep_plot.m, or RADA_LQG_sep_ol_plot.m files and rename the structures for your test. These files create four figures. Figure 1 plots compares the x velocity data in the first sub figure and compares pitch (theta) data in the second sub figure. Figure 2 does the same thing as Figure 1 but with y velocity and roll data. Figure 3 looks at the yaw data. Finally, Figure 4 looks at the sample period between UAV and ERIS packets from the camera system just to check for periods of time with large packet drops. You can follow a similar pattern to compare motor commands. Just make sure that you compare Quad Motor 2 from the test data with Quad Motor 4 from simulation and vise versa because propellers 2 and 4 were switch in Eris's software compared to the Model. That is all you need to know for testing RADA against the model. 71d6fbd4c2333d42e36c53dcf5823355ae81d831 331 330 2016-09-21T14:46:23Z Jonessk 7 /* Turing on RADA */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. The initial setup and how to test the system can also be applied to demoing RADA. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging Batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supply because it is the only power supply that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} The YouTube video link above should explain how to use the charger. RADA currently uses three different Lithium polymer (Lipo) batteries: 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo for the propellers. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery voltage drops really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAh 4-cell generally charge in 10-20 minutes apiece while the 2600 mAh 2-cell generally take up to 70 minutes to charge fully. === Setting up the Camera System === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password (not posted here for security reasons, but any one who works in the lab should know it). Once logged in, look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should have the naming scheme ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by date modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in the main project screen arrange themselves like the camera system configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another popup window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They have the naming scheme ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackables are open, the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation, left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't, the front is the side opposite the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system. If the system is aligned, you should be able to block the mounting bolts of the front propeller motor with the pole while facing the east wall. 4. While holding the pendulum approximately vertical, see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and within a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise, go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directions and hold it there. - With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation button'' - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to ''File->Save Trackables...'' and save a file using the same naming conventions as the trackable file you opened earlier. Use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use (the password isn't put here for security reasons). First, ensure that the RADA software is setup correctly for the test you want to run. To do this, you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below are compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also causes the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propellers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by an LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to accelerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packet drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA Senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have found that even on a good strt the ''[ok]'' messages will still print. === Turning on RADA === Turning on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the switches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you use EITHER the WIFI adapter OR hardwired Ethernet, because the VRPN may listen to the camera data broadcast over both connections which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in, you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup with out needing to close the connection. If you are using a WIFI connect use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connaction use the command ''ssh root@192.168.0.54''. If the connection goes though you should be proped for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the first test after power up === For the firs test after powering on Eris a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect the the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell scrip will setup the NFS, load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject and runs the executable. Once the user exits the executable the log file produces is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see an warning that when coping the log file Eris couldn't maintain the file permisiion settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This Date stamp uses date on Eris which is currently in June of 2008 as of August 2nd, 2016. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA, you will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after start up you don't need to run this script. See the Section about Running additional tests below. [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode you can use the following commands to enter the desired mode with a three second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode, this will only really work when using PIDs to control the pendulum. -''b'' : Enter Robot control mode, in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode, where the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file incase odd things happen somewhere. This just increments a counter so if you use it look for changes in the marker value. ==== Robot Control Model ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box set mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use he same commands as Tuning Mode. === Running additional Tests === Once you have run one test with Eris on it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_stat_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result it is ready to test much quicker. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and retrieving log files === If you are only demoing the system there is no need to go beyond this point. Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files are named like ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful of describing what the test was of or for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring battery voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there isn't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log is the headder. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value latter. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== 1. After test disconnect wheel battery from the system. 2. Measure voltage of battery using multimeter. [[Image:MeasureVwheel.jpg|800px]] You can use the plug used for charging the 2-cell Lipos but make sure to connect the plug to the multimeter before connecting the battery and disconnect the battery before disconnecting the plug from the mulitmeter. It is generally the best practice to give the multimeter a few minutes to allow for the voltage measurement to stabilize as the battery measurement tends to be a little low right after the test. The multimeter will report data out to four decimal places it is best just to round to three decimal places for the wheel voltage. ==== Quad Battery ==== 1. Setup code to run all four propellers at 50% throttle, uncomment the definition of ''mot50'' in main.cpp and compile the project. 2. Power off propellers by turning off the switch to the ESCs. 3. Connect multimeter to measure the voltage across one of the ESCs. This is done by using the power splitter cord. -Connect one of the female XT60 connectors on the splitter to a male XT60 connector to banana connector cable. -The banana connector connect to the hand held multimeter. The multimeter should be set to the 20VDC measurement setting. -Next unplug one the ESCs' power connection. -reconnect the ESC to power through the two remain connectors on the spliter cable. 4. Power on the propellers. 5. Run the system at 50% throttle and measure the steady-state voltage during the test. The battery will slow the voltage decay significantly, meaning it will keep the same measurement for a few seconds. 6. Stop the test and record the voltage in the log file. Make sure to disconnect the batter before removing the splitter cable. {| class="wikitable" style="text-align:center" |- | [[Image:PowerSplitter.jpg|200px]] | [[Image:QuadMultiCon.jpg |200px]] | [[Image:QuadMultiSet.JPG |200px]] | [[Image:QuadMeasESCcon.JPG|200px]] |- | Splitter cord. | Connect splitter to multimeter. | Settings for multimeter. | Connecting ESC through splitter. |} The testing setup should look like the image below: [[Image:QuadBattMeas.jpg|800px]] == Post processing and Simulation == Simulating a test of RADA starts with processing and storing the data. Then all of the parameters of the model are loaded in the MATLAB Workspace. Finally the Simulink file used for the simulation is opened and the length of the simulation is set to match the length of the actual test. The simulation is run and the simulation output is stored. Finally the data should be plotted and compared. === Using the MATLAB data parsing tool === In depth discussion of how to use the log file parsing tool is described [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] I suggest using the version of the tool in the rada_resarch_project git repository Paul Uhing used for his Master's research. It con be found on CO3050-11 under the ucart account in the directory ''~/rada_research_project/DataAnalysiTool_omnicoor/Tool''. Simply open MATLAB and set the working directory to this file path. In the MATLAB Command Prompt run ''DataAnalysis''. A popup window should open up. Select the log file you want to process and wait for the tool to finish processing the file. Once this is complete there should be four structures in the MATLAB workspace. -'''main''' : This contains all of the data extracted from the log file and the processing parameters used. main.expData contains two time structures: Time is used for the pendulum data and Eris_time is used for the ground vehicle data. -'''X_ref''' : This contains the reference vector in m/s for x velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Y_ref''' : This contains the reference vector in m/s for y velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Yaw_ref''' : This contains the reference vector in radians for yaw that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. This one is new incase people start testing the system with heading changes but is not used in the current setup. The first thing you should do is rename the main structure to the name you used for the log file. This is helpful for comparing multiple tests. Next you will want to crate two new variable ''Vquad_test'' an Vw_test''. In the MATLAB Command Prompt set the measured propeller voltage from the log file to ''Vquad_test'' and set the measured the wheel voltage to ''Vw_test'' as this will be used by the simulation. Finally if you did an open-loop test of the wheels create the variable ''Uol'' and set it to the open-loop wheel command used. Save all of these variables from the MATLAB workspace to a ''.mat'' file of the same name as log file you extracted the data from and save it in the same directory as your RADA Simulink files. As of August 2nd, 2016 this directory is ''~/rada_research_project/MATLAB/RADA.'' === Setting up the MATLAB workspace for simulation === Change your MATLAB directory to this directory. Then run the simulation setup files. Currently you just need to run ''modelParams_smallWheels_RADA'' in the MATLAB Command Prompt. Next open the Simulink file with that contains the model of RADA controlled by the controller you tested. -'''RADA_psiCtrl_v2_lqi_est.slx''' contains LQI, LQI+estimation, and LQG controller simulations. -'''RADA_psiCtrl_v2.slx''' contains the PID controlled system. -'''RADA_psiCtrl_v2_LQGsep.slx''' contains the subsystem LQG controlled system. -'''RADA_psiCtrl_v2_LQGsep_ol.slx''' contains the simulation of the pendulum system controlled by an LQG and Eris controlled with open-loop commands. Note all of the current (August 2nd, 2016) ''.slx'' files were created in MATLAB 2014b and will only work in MATLAB 2014B or newer. Then in the MATLAB Command Prompt type ''X_ref.time(end)'' exactly, don't add a semicolon, and hit enter. MATLAB will print the time of the last command in the X_ref structure. Set the en time of the simulation to this value and save your Simulink file. === Running simulations and storing results === Before running the simulation make sure that the simuation is using the ''ode23t'' differential equations solver. This system is a moderately stiff system of differential and the ''ode45'' solver doesn't do well with these types of systems. When using ''ode23t'' is should only take a few minutes to run a 100+ second simulation while doing the same test using ''ode45'' could take 8 hours. While this slow it is also bad for your hard drive as the simulation has to page between RAM and your computers hard drive a lot. Once this check is done run the simulation. While it is running check what the output structures variables are named for for your RADA test system. Once the simulation is done go to your MATLAB Workspace and select all 15 outputs for your simulation or your sub-simulation if you used '''RADA_psiCtrl_v2_lqi_est.slx'''. Save these 15 output structures to a ''.mat'' file named as the log file with _sim appended to the end of the name. The 15 outputs are structures containing a time vector and then the data from the simulation sampled at 100 Hz and the units of this data are the SI units (ex: radians, m/s). There is one output structure for x velocity, y velocity, x body velocity, y body velocity, theta (pitch), phi (roll), psi (yaw), and one per actuator command (ex: the command sent to a wheel). Now you have all the data you can plot it. === Plotting results === If you look at the ''DataSets'' folder below ''~/rada_research_project/MATLAB/RADA'' directory there are plenty of examples of how Paul Uhing compared simulation to test data. Generally you should grate a ''.m'' file with the same name as the log file this data was extracted from with _plot appended to the name. Generally you can just copy an for RADA_LQG_compPID_plot.m RADA_PID_compLQG_plot.m, RADA_LQG_sep_plot.m, or RADA_LQG_sep_ol_plot.m files and rename the structures for your test. These files create four figures. Figure 1 plots compares the x velocity data in the first sub figure and compares pitch (theta) data in the second sub figure. Figure 2 does the same thing as Figure 1 but with y velocity and roll data. Figure 3 looks at the yaw data. Finally, Figure 4 looks at the sample period between UAV and ERIS packets from the camera system just to check for periods of time with large packet drops. You can follow a similar pattern to compare motor commands. Just make sure that you compare Quad Motor 2 from the test data with Quad Motor 4 from simulation and vise versa because propellers 2 and 4 were switch in Eris's software compared to the Model. That is all you need to know for testing RADA against the model. 446f46a19dca6e95e0956ba3476fc055a89e7a28 332 331 2016-09-21T14:48:36Z Jonessk 7 /* Connecting to RADA */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. The initial setup and how to test the system can also be applied to demoing RADA. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging Batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supply because it is the only power supply that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} The YouTube video link above should explain how to use the charger. RADA currently uses three different Lithium polymer (Lipo) batteries: 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo for the propellers. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery voltage drops really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAh 4-cell generally charge in 10-20 minutes apiece while the 2600 mAh 2-cell generally take up to 70 minutes to charge fully. === Setting up the Camera System === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password (not posted here for security reasons, but any one who works in the lab should know it). Once logged in, look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should have the naming scheme ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by date modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in the main project screen arrange themselves like the camera system configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another popup window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They have the naming scheme ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackables are open, the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation, left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't, the front is the side opposite the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system. If the system is aligned, you should be able to block the mounting bolts of the front propeller motor with the pole while facing the east wall. 4. While holding the pendulum approximately vertical, see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and within a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise, go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directions and hold it there. - With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation button'' - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to ''File->Save Trackables...'' and save a file using the same naming conventions as the trackable file you opened earlier. Use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use (the password isn't put here for security reasons). First, ensure that the RADA software is setup correctly for the test you want to run. To do this, you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below are compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also causes the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propellers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by an LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to accelerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packet drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA Senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have found that even on a good strt the ''[ok]'' messages will still print. === Turning on RADA === Turning on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the switches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you use EITHER the WIFI adapter OR hardwired Ethernet, because the VRPN may listen to the camera data broadcast over both connections which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in, you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup without needing to close the connection. If you are using a WIFI connection use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connection use the command ''ssh root@192.168.0.54''. If the connection goes though you should be prompted for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the first test after power up === For the firs test after powering on Eris a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect the the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell scrip will setup the NFS, load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject and runs the executable. Once the user exits the executable the log file produces is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see an warning that when coping the log file Eris couldn't maintain the file permisiion settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This Date stamp uses date on Eris which is currently in June of 2008 as of August 2nd, 2016. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA, you will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after start up you don't need to run this script. See the Section about Running additional tests below. [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode you can use the following commands to enter the desired mode with a three second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode, this will only really work when using PIDs to control the pendulum. -''b'' : Enter Robot control mode, in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode, where the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file incase odd things happen somewhere. This just increments a counter so if you use it look for changes in the marker value. ==== Robot Control Model ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box set mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use he same commands as Tuning Mode. === Running additional Tests === Once you have run one test with Eris on it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_stat_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result it is ready to test much quicker. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and retrieving log files === If you are only demoing the system there is no need to go beyond this point. Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files are named like ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful of describing what the test was of or for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring battery voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there isn't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log is the headder. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value latter. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== 1. After test disconnect wheel battery from the system. 2. Measure voltage of battery using multimeter. [[Image:MeasureVwheel.jpg|800px]] You can use the plug used for charging the 2-cell Lipos but make sure to connect the plug to the multimeter before connecting the battery and disconnect the battery before disconnecting the plug from the mulitmeter. It is generally the best practice to give the multimeter a few minutes to allow for the voltage measurement to stabilize as the battery measurement tends to be a little low right after the test. The multimeter will report data out to four decimal places it is best just to round to three decimal places for the wheel voltage. ==== Quad Battery ==== 1. Setup code to run all four propellers at 50% throttle, uncomment the definition of ''mot50'' in main.cpp and compile the project. 2. Power off propellers by turning off the switch to the ESCs. 3. Connect multimeter to measure the voltage across one of the ESCs. This is done by using the power splitter cord. -Connect one of the female XT60 connectors on the splitter to a male XT60 connector to banana connector cable. -The banana connector connect to the hand held multimeter. The multimeter should be set to the 20VDC measurement setting. -Next unplug one the ESCs' power connection. -reconnect the ESC to power through the two remain connectors on the spliter cable. 4. Power on the propellers. 5. Run the system at 50% throttle and measure the steady-state voltage during the test. The battery will slow the voltage decay significantly, meaning it will keep the same measurement for a few seconds. 6. Stop the test and record the voltage in the log file. Make sure to disconnect the batter before removing the splitter cable. {| class="wikitable" style="text-align:center" |- | [[Image:PowerSplitter.jpg|200px]] | [[Image:QuadMultiCon.jpg |200px]] | [[Image:QuadMultiSet.JPG |200px]] | [[Image:QuadMeasESCcon.JPG|200px]] |- | Splitter cord. | Connect splitter to multimeter. | Settings for multimeter. | Connecting ESC through splitter. |} The testing setup should look like the image below: [[Image:QuadBattMeas.jpg|800px]] == Post processing and Simulation == Simulating a test of RADA starts with processing and storing the data. Then all of the parameters of the model are loaded in the MATLAB Workspace. Finally the Simulink file used for the simulation is opened and the length of the simulation is set to match the length of the actual test. The simulation is run and the simulation output is stored. Finally the data should be plotted and compared. === Using the MATLAB data parsing tool === In depth discussion of how to use the log file parsing tool is described [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] I suggest using the version of the tool in the rada_resarch_project git repository Paul Uhing used for his Master's research. It con be found on CO3050-11 under the ucart account in the directory ''~/rada_research_project/DataAnalysiTool_omnicoor/Tool''. Simply open MATLAB and set the working directory to this file path. In the MATLAB Command Prompt run ''DataAnalysis''. A popup window should open up. Select the log file you want to process and wait for the tool to finish processing the file. Once this is complete there should be four structures in the MATLAB workspace. -'''main''' : This contains all of the data extracted from the log file and the processing parameters used. main.expData contains two time structures: Time is used for the pendulum data and Eris_time is used for the ground vehicle data. -'''X_ref''' : This contains the reference vector in m/s for x velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Y_ref''' : This contains the reference vector in m/s for y velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Yaw_ref''' : This contains the reference vector in radians for yaw that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. This one is new incase people start testing the system with heading changes but is not used in the current setup. The first thing you should do is rename the main structure to the name you used for the log file. This is helpful for comparing multiple tests. Next you will want to crate two new variable ''Vquad_test'' an Vw_test''. In the MATLAB Command Prompt set the measured propeller voltage from the log file to ''Vquad_test'' and set the measured the wheel voltage to ''Vw_test'' as this will be used by the simulation. Finally if you did an open-loop test of the wheels create the variable ''Uol'' and set it to the open-loop wheel command used. Save all of these variables from the MATLAB workspace to a ''.mat'' file of the same name as log file you extracted the data from and save it in the same directory as your RADA Simulink files. As of August 2nd, 2016 this directory is ''~/rada_research_project/MATLAB/RADA.'' === Setting up the MATLAB workspace for simulation === Change your MATLAB directory to this directory. Then run the simulation setup files. Currently you just need to run ''modelParams_smallWheels_RADA'' in the MATLAB Command Prompt. Next open the Simulink file with that contains the model of RADA controlled by the controller you tested. -'''RADA_psiCtrl_v2_lqi_est.slx''' contains LQI, LQI+estimation, and LQG controller simulations. -'''RADA_psiCtrl_v2.slx''' contains the PID controlled system. -'''RADA_psiCtrl_v2_LQGsep.slx''' contains the subsystem LQG controlled system. -'''RADA_psiCtrl_v2_LQGsep_ol.slx''' contains the simulation of the pendulum system controlled by an LQG and Eris controlled with open-loop commands. Note all of the current (August 2nd, 2016) ''.slx'' files were created in MATLAB 2014b and will only work in MATLAB 2014B or newer. Then in the MATLAB Command Prompt type ''X_ref.time(end)'' exactly, don't add a semicolon, and hit enter. MATLAB will print the time of the last command in the X_ref structure. Set the en time of the simulation to this value and save your Simulink file. === Running simulations and storing results === Before running the simulation make sure that the simuation is using the ''ode23t'' differential equations solver. This system is a moderately stiff system of differential and the ''ode45'' solver doesn't do well with these types of systems. When using ''ode23t'' is should only take a few minutes to run a 100+ second simulation while doing the same test using ''ode45'' could take 8 hours. While this slow it is also bad for your hard drive as the simulation has to page between RAM and your computers hard drive a lot. Once this check is done run the simulation. While it is running check what the output structures variables are named for for your RADA test system. Once the simulation is done go to your MATLAB Workspace and select all 15 outputs for your simulation or your sub-simulation if you used '''RADA_psiCtrl_v2_lqi_est.slx'''. Save these 15 output structures to a ''.mat'' file named as the log file with _sim appended to the end of the name. The 15 outputs are structures containing a time vector and then the data from the simulation sampled at 100 Hz and the units of this data are the SI units (ex: radians, m/s). There is one output structure for x velocity, y velocity, x body velocity, y body velocity, theta (pitch), phi (roll), psi (yaw), and one per actuator command (ex: the command sent to a wheel). Now you have all the data you can plot it. === Plotting results === If you look at the ''DataSets'' folder below ''~/rada_research_project/MATLAB/RADA'' directory there are plenty of examples of how Paul Uhing compared simulation to test data. Generally you should grate a ''.m'' file with the same name as the log file this data was extracted from with _plot appended to the name. Generally you can just copy an for RADA_LQG_compPID_plot.m RADA_PID_compLQG_plot.m, RADA_LQG_sep_plot.m, or RADA_LQG_sep_ol_plot.m files and rename the structures for your test. These files create four figures. Figure 1 plots compares the x velocity data in the first sub figure and compares pitch (theta) data in the second sub figure. Figure 2 does the same thing as Figure 1 but with y velocity and roll data. Figure 3 looks at the yaw data. Finally, Figure 4 looks at the sample period between UAV and ERIS packets from the camera system just to check for periods of time with large packet drops. You can follow a similar pattern to compare motor commands. Just make sure that you compare Quad Motor 2 from the test data with Quad Motor 4 from simulation and vise versa because propellers 2 and 4 were switch in Eris's software compared to the Model. That is all you need to know for testing RADA against the model. 3fb26c626a752c3855ddd56a5896efdc9495d768 333 332 2016-09-21T14:53:51Z Jonessk 7 /* Running the first test after power up */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. The initial setup and how to test the system can also be applied to demoing RADA. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging Batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supply because it is the only power supply that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} The YouTube video link above should explain how to use the charger. RADA currently uses three different Lithium polymer (Lipo) batteries: 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo for the propellers. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery voltage drops really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAh 4-cell generally charge in 10-20 minutes apiece while the 2600 mAh 2-cell generally take up to 70 minutes to charge fully. === Setting up the Camera System === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password (not posted here for security reasons, but any one who works in the lab should know it). Once logged in, look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should have the naming scheme ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by date modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in the main project screen arrange themselves like the camera system configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another popup window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They have the naming scheme ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackables are open, the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation, left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need check to make sure the system is zeroed. 1. Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't, the front is the side opposite the switches and the side with the trackable constellation on it. 2. Make sure that the motor with the red motor mount is also facing the wall with the white boards. 3. Make sure the quad system is aligned along Eris Axis by standing behind the system. If the system is aligned, you should be able to block the mounting bolts of the front propeller motor with the pole while facing the east wall. 4. While holding the pendulum approximately vertical, see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. 5. Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and within a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise, go to the next step. 6. You need to zero the pendulum. - Align ERIS so it is near zero yaw first (eye ball it). - Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directions and hold it there. - With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation button'' - Now your friend can set the pendulum down and you can zero ERIS the same way. 7. Save the new trackable orientation by going to ''File->Save Trackables...'' and save a file using the same naming conventions as the trackable file you opened earlier. Use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use (the password isn't put here for security reasons). First, ensure that the RADA software is setup correctly for the test you want to run. To do this, you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below are compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also causes the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propellers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by an LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to accelerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packet drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA Senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have found that even on a good strt the ''[ok]'' messages will still print. === Turning on RADA === Turning on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the switches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you use EITHER the WIFI adapter OR hardwired Ethernet, because the VRPN may listen to the camera data broadcast over both connections which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in, you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup without needing to close the connection. If you are using a WIFI connection use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connection use the command ''ssh root@192.168.0.54''. If the connection goes though you should be prompted for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the First Test After Power Up === For the first test after powering on Eris, a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect to the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell script will setup the NFS, and load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject'' and runs the executable. Once the user exits the executable, the log file produced is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see a warning that when copying the log file Eris couldn't maintain the file permission settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This date stamp uses the date on Eris, which is currently in June of 2008 as of August 2nd, 2016. Before starting the test, it is best to have someone spotting the pendulum and holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once the spotter is ready, run the shell script by using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA. You will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after startup you don't need to run this script. See the Section about Running additional tests below.r [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode you can use the following commands to enter the desired mode with a three second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode, this will only really work when using PIDs to control the pendulum. -''b'' : Enter Robot control mode, in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode, where the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file incase odd things happen somewhere. This just increments a counter so if you use it look for changes in the marker value. ==== Robot Control Model ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box set mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use he same commands as Tuning Mode. === Running additional Tests === Once you have run one test with Eris on it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_stat_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result it is ready to test much quicker. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and retrieving log files === If you are only demoing the system there is no need to go beyond this point. Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files are named like ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful of describing what the test was of or for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring battery voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there isn't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log is the headder. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value latter. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== 1. After test disconnect wheel battery from the system. 2. Measure voltage of battery using multimeter. [[Image:MeasureVwheel.jpg|800px]] You can use the plug used for charging the 2-cell Lipos but make sure to connect the plug to the multimeter before connecting the battery and disconnect the battery before disconnecting the plug from the mulitmeter. It is generally the best practice to give the multimeter a few minutes to allow for the voltage measurement to stabilize as the battery measurement tends to be a little low right after the test. The multimeter will report data out to four decimal places it is best just to round to three decimal places for the wheel voltage. ==== Quad Battery ==== 1. Setup code to run all four propellers at 50% throttle, uncomment the definition of ''mot50'' in main.cpp and compile the project. 2. Power off propellers by turning off the switch to the ESCs. 3. Connect multimeter to measure the voltage across one of the ESCs. This is done by using the power splitter cord. -Connect one of the female XT60 connectors on the splitter to a male XT60 connector to banana connector cable. -The banana connector connect to the hand held multimeter. The multimeter should be set to the 20VDC measurement setting. -Next unplug one the ESCs' power connection. -reconnect the ESC to power through the two remain connectors on the spliter cable. 4. Power on the propellers. 5. Run the system at 50% throttle and measure the steady-state voltage during the test. The battery will slow the voltage decay significantly, meaning it will keep the same measurement for a few seconds. 6. Stop the test and record the voltage in the log file. Make sure to disconnect the batter before removing the splitter cable. {| class="wikitable" style="text-align:center" |- | [[Image:PowerSplitter.jpg|200px]] | [[Image:QuadMultiCon.jpg |200px]] | [[Image:QuadMultiSet.JPG |200px]] | [[Image:QuadMeasESCcon.JPG|200px]] |- | Splitter cord. | Connect splitter to multimeter. | Settings for multimeter. | Connecting ESC through splitter. |} The testing setup should look like the image below: [[Image:QuadBattMeas.jpg|800px]] == Post processing and Simulation == Simulating a test of RADA starts with processing and storing the data. Then all of the parameters of the model are loaded in the MATLAB Workspace. Finally the Simulink file used for the simulation is opened and the length of the simulation is set to match the length of the actual test. The simulation is run and the simulation output is stored. Finally the data should be plotted and compared. === Using the MATLAB data parsing tool === In depth discussion of how to use the log file parsing tool is described [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] I suggest using the version of the tool in the rada_resarch_project git repository Paul Uhing used for his Master's research. It con be found on CO3050-11 under the ucart account in the directory ''~/rada_research_project/DataAnalysiTool_omnicoor/Tool''. Simply open MATLAB and set the working directory to this file path. In the MATLAB Command Prompt run ''DataAnalysis''. A popup window should open up. Select the log file you want to process and wait for the tool to finish processing the file. Once this is complete there should be four structures in the MATLAB workspace. -'''main''' : This contains all of the data extracted from the log file and the processing parameters used. main.expData contains two time structures: Time is used for the pendulum data and Eris_time is used for the ground vehicle data. -'''X_ref''' : This contains the reference vector in m/s for x velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Y_ref''' : This contains the reference vector in m/s for y velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Yaw_ref''' : This contains the reference vector in radians for yaw that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. This one is new incase people start testing the system with heading changes but is not used in the current setup. The first thing you should do is rename the main structure to the name you used for the log file. This is helpful for comparing multiple tests. Next you will want to crate two new variable ''Vquad_test'' an Vw_test''. In the MATLAB Command Prompt set the measured propeller voltage from the log file to ''Vquad_test'' and set the measured the wheel voltage to ''Vw_test'' as this will be used by the simulation. Finally if you did an open-loop test of the wheels create the variable ''Uol'' and set it to the open-loop wheel command used. Save all of these variables from the MATLAB workspace to a ''.mat'' file of the same name as log file you extracted the data from and save it in the same directory as your RADA Simulink files. As of August 2nd, 2016 this directory is ''~/rada_research_project/MATLAB/RADA.'' === Setting up the MATLAB workspace for simulation === Change your MATLAB directory to this directory. Then run the simulation setup files. Currently you just need to run ''modelParams_smallWheels_RADA'' in the MATLAB Command Prompt. Next open the Simulink file with that contains the model of RADA controlled by the controller you tested. -'''RADA_psiCtrl_v2_lqi_est.slx''' contains LQI, LQI+estimation, and LQG controller simulations. -'''RADA_psiCtrl_v2.slx''' contains the PID controlled system. -'''RADA_psiCtrl_v2_LQGsep.slx''' contains the subsystem LQG controlled system. -'''RADA_psiCtrl_v2_LQGsep_ol.slx''' contains the simulation of the pendulum system controlled by an LQG and Eris controlled with open-loop commands. Note all of the current (August 2nd, 2016) ''.slx'' files were created in MATLAB 2014b and will only work in MATLAB 2014B or newer. Then in the MATLAB Command Prompt type ''X_ref.time(end)'' exactly, don't add a semicolon, and hit enter. MATLAB will print the time of the last command in the X_ref structure. Set the en time of the simulation to this value and save your Simulink file. === Running simulations and storing results === Before running the simulation make sure that the simuation is using the ''ode23t'' differential equations solver. This system is a moderately stiff system of differential and the ''ode45'' solver doesn't do well with these types of systems. When using ''ode23t'' is should only take a few minutes to run a 100+ second simulation while doing the same test using ''ode45'' could take 8 hours. While this slow it is also bad for your hard drive as the simulation has to page between RAM and your computers hard drive a lot. Once this check is done run the simulation. While it is running check what the output structures variables are named for for your RADA test system. Once the simulation is done go to your MATLAB Workspace and select all 15 outputs for your simulation or your sub-simulation if you used '''RADA_psiCtrl_v2_lqi_est.slx'''. Save these 15 output structures to a ''.mat'' file named as the log file with _sim appended to the end of the name. The 15 outputs are structures containing a time vector and then the data from the simulation sampled at 100 Hz and the units of this data are the SI units (ex: radians, m/s). There is one output structure for x velocity, y velocity, x body velocity, y body velocity, theta (pitch), phi (roll), psi (yaw), and one per actuator command (ex: the command sent to a wheel). Now you have all the data you can plot it. === Plotting results === If you look at the ''DataSets'' folder below ''~/rada_research_project/MATLAB/RADA'' directory there are plenty of examples of how Paul Uhing compared simulation to test data. Generally you should grate a ''.m'' file with the same name as the log file this data was extracted from with _plot appended to the name. Generally you can just copy an for RADA_LQG_compPID_plot.m RADA_PID_compLQG_plot.m, RADA_LQG_sep_plot.m, or RADA_LQG_sep_ol_plot.m files and rename the structures for your test. These files create four figures. Figure 1 plots compares the x velocity data in the first sub figure and compares pitch (theta) data in the second sub figure. Figure 2 does the same thing as Figure 1 but with y velocity and roll data. Figure 3 looks at the yaw data. Finally, Figure 4 looks at the sample period between UAV and ERIS packets from the camera system just to check for periods of time with large packet drops. You can follow a similar pattern to compare motor commands. Just make sure that you compare Quad Motor 2 from the test data with Quad Motor 4 from simulation and vise versa because propellers 2 and 4 were switch in Eris's software compared to the Model. That is all you need to know for testing RADA against the model. 74052511bc9a81e54398dec64f9827e65d213aa4 337 333 2016-09-21T23:29:26Z Jonessk 7 /* Setting up the Camera System */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. The initial setup and how to test the system can also be applied to demoing RADA. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging Batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supply because it is the only power supply that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} The YouTube video link above should explain how to use the charger. RADA currently uses three different Lithium polymer (Lipo) batteries: 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo for the propellers. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery voltage drops really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAh 4-cell generally charge in 10-20 minutes apiece while the 2600 mAh 2-cell generally take up to 70 minutes to charge fully. === Setting up the Camera System === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password (not posted here for security reasons, but any one who works in the lab should know it). Once logged in, look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should have the naming scheme ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by date modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in the main project screen arrange themselves like the camera system configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another popup window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They have the naming scheme ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackables are open, the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation, left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need to check to make sure the system is zeroed. #Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't, the front is the side opposite the switches and the side with the trackable constellation on it. #Make sure that the motor with the red motor mount is also facing the wall with the white boards. #Make sure the quad system is aligned along Eris Axis by standing behind the system. If the system is aligned, you should be able to block the mounting bolts of the front propeller motor with the pole while facing the east wall. #While holding the pendulum approximately vertical, see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. #Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and within a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise, go to the next step. #You need to zero the pendulum. ##Align ERIS so it is near zero yaw first (eye ball it). ##Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directions and hold it there. ##With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation button'' ##Now your friend can set the pendulum down and you can zero ERIS the same way. #Save the new trackable orientation by going to ''File->Save Trackables...'' and save a file using the same naming conventions as the trackable file you opened earlier. Use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use (the password isn't put here for security reasons). First, ensure that the RADA software is setup correctly for the test you want to run. To do this, you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below are compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also causes the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propellers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by an LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to accelerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packet drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA Senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have found that even on a good strt the ''[ok]'' messages will still print. === Turning on RADA === Turning on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the switches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you use EITHER the WIFI adapter OR hardwired Ethernet, because the VRPN may listen to the camera data broadcast over both connections which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in, you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup without needing to close the connection. If you are using a WIFI connection use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connection use the command ''ssh root@192.168.0.54''. If the connection goes though you should be prompted for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the First Test After Power Up === For the first test after powering on Eris, a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect to the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell script will setup the NFS, and load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject'' and runs the executable. Once the user exits the executable, the log file produced is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see a warning that when copying the log file Eris couldn't maintain the file permission settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This date stamp uses the date on Eris, which is currently in June of 2008 as of August 2nd, 2016. Before starting the test, it is best to have someone spotting the pendulum and holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once the spotter is ready, run the shell script by using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA. You will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after startup you don't need to run this script. See the Section about Running additional tests below.r [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode you can use the following commands to enter the desired mode with a three second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode, this will only really work when using PIDs to control the pendulum. -''b'' : Enter Robot control mode, in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode, where the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file incase odd things happen somewhere. This just increments a counter so if you use it look for changes in the marker value. ==== Robot Control Model ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box set mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use he same commands as Tuning Mode. === Running additional Tests === Once you have run one test with Eris on it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_stat_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result it is ready to test much quicker. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and retrieving log files === If you are only demoing the system there is no need to go beyond this point. Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files are named like ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful of describing what the test was of or for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring battery voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there isn't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log is the headder. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value latter. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== 1. After test disconnect wheel battery from the system. 2. Measure voltage of battery using multimeter. [[Image:MeasureVwheel.jpg|800px]] You can use the plug used for charging the 2-cell Lipos but make sure to connect the plug to the multimeter before connecting the battery and disconnect the battery before disconnecting the plug from the mulitmeter. It is generally the best practice to give the multimeter a few minutes to allow for the voltage measurement to stabilize as the battery measurement tends to be a little low right after the test. The multimeter will report data out to four decimal places it is best just to round to three decimal places for the wheel voltage. ==== Quad Battery ==== 1. Setup code to run all four propellers at 50% throttle, uncomment the definition of ''mot50'' in main.cpp and compile the project. 2. Power off propellers by turning off the switch to the ESCs. 3. Connect multimeter to measure the voltage across one of the ESCs. This is done by using the power splitter cord. -Connect one of the female XT60 connectors on the splitter to a male XT60 connector to banana connector cable. -The banana connector connect to the hand held multimeter. The multimeter should be set to the 20VDC measurement setting. -Next unplug one the ESCs' power connection. -reconnect the ESC to power through the two remain connectors on the spliter cable. 4. Power on the propellers. 5. Run the system at 50% throttle and measure the steady-state voltage during the test. The battery will slow the voltage decay significantly, meaning it will keep the same measurement for a few seconds. 6. Stop the test and record the voltage in the log file. Make sure to disconnect the batter before removing the splitter cable. {| class="wikitable" style="text-align:center" |- | [[Image:PowerSplitter.jpg|200px]] | [[Image:QuadMultiCon.jpg |200px]] | [[Image:QuadMultiSet.JPG |200px]] | [[Image:QuadMeasESCcon.JPG|200px]] |- | Splitter cord. | Connect splitter to multimeter. | Settings for multimeter. | Connecting ESC through splitter. |} The testing setup should look like the image below: [[Image:QuadBattMeas.jpg|800px]] == Post processing and Simulation == Simulating a test of RADA starts with processing and storing the data. Then all of the parameters of the model are loaded in the MATLAB Workspace. Finally the Simulink file used for the simulation is opened and the length of the simulation is set to match the length of the actual test. The simulation is run and the simulation output is stored. Finally the data should be plotted and compared. === Using the MATLAB data parsing tool === In depth discussion of how to use the log file parsing tool is described [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] I suggest using the version of the tool in the rada_resarch_project git repository Paul Uhing used for his Master's research. It con be found on CO3050-11 under the ucart account in the directory ''~/rada_research_project/DataAnalysiTool_omnicoor/Tool''. Simply open MATLAB and set the working directory to this file path. In the MATLAB Command Prompt run ''DataAnalysis''. A popup window should open up. Select the log file you want to process and wait for the tool to finish processing the file. Once this is complete there should be four structures in the MATLAB workspace. -'''main''' : This contains all of the data extracted from the log file and the processing parameters used. main.expData contains two time structures: Time is used for the pendulum data and Eris_time is used for the ground vehicle data. -'''X_ref''' : This contains the reference vector in m/s for x velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Y_ref''' : This contains the reference vector in m/s for y velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Yaw_ref''' : This contains the reference vector in radians for yaw that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. This one is new incase people start testing the system with heading changes but is not used in the current setup. The first thing you should do is rename the main structure to the name you used for the log file. This is helpful for comparing multiple tests. Next you will want to crate two new variable ''Vquad_test'' an Vw_test''. In the MATLAB Command Prompt set the measured propeller voltage from the log file to ''Vquad_test'' and set the measured the wheel voltage to ''Vw_test'' as this will be used by the simulation. Finally if you did an open-loop test of the wheels create the variable ''Uol'' and set it to the open-loop wheel command used. Save all of these variables from the MATLAB workspace to a ''.mat'' file of the same name as log file you extracted the data from and save it in the same directory as your RADA Simulink files. As of August 2nd, 2016 this directory is ''~/rada_research_project/MATLAB/RADA.'' === Setting up the MATLAB workspace for simulation === Change your MATLAB directory to this directory. Then run the simulation setup files. Currently you just need to run ''modelParams_smallWheels_RADA'' in the MATLAB Command Prompt. Next open the Simulink file with that contains the model of RADA controlled by the controller you tested. -'''RADA_psiCtrl_v2_lqi_est.slx''' contains LQI, LQI+estimation, and LQG controller simulations. -'''RADA_psiCtrl_v2.slx''' contains the PID controlled system. -'''RADA_psiCtrl_v2_LQGsep.slx''' contains the subsystem LQG controlled system. -'''RADA_psiCtrl_v2_LQGsep_ol.slx''' contains the simulation of the pendulum system controlled by an LQG and Eris controlled with open-loop commands. Note all of the current (August 2nd, 2016) ''.slx'' files were created in MATLAB 2014b and will only work in MATLAB 2014B or newer. Then in the MATLAB Command Prompt type ''X_ref.time(end)'' exactly, don't add a semicolon, and hit enter. MATLAB will print the time of the last command in the X_ref structure. Set the en time of the simulation to this value and save your Simulink file. === Running simulations and storing results === Before running the simulation make sure that the simuation is using the ''ode23t'' differential equations solver. This system is a moderately stiff system of differential and the ''ode45'' solver doesn't do well with these types of systems. When using ''ode23t'' is should only take a few minutes to run a 100+ second simulation while doing the same test using ''ode45'' could take 8 hours. While this slow it is also bad for your hard drive as the simulation has to page between RAM and your computers hard drive a lot. Once this check is done run the simulation. While it is running check what the output structures variables are named for for your RADA test system. Once the simulation is done go to your MATLAB Workspace and select all 15 outputs for your simulation or your sub-simulation if you used '''RADA_psiCtrl_v2_lqi_est.slx'''. Save these 15 output structures to a ''.mat'' file named as the log file with _sim appended to the end of the name. The 15 outputs are structures containing a time vector and then the data from the simulation sampled at 100 Hz and the units of this data are the SI units (ex: radians, m/s). There is one output structure for x velocity, y velocity, x body velocity, y body velocity, theta (pitch), phi (roll), psi (yaw), and one per actuator command (ex: the command sent to a wheel). Now you have all the data you can plot it. === Plotting results === If you look at the ''DataSets'' folder below ''~/rada_research_project/MATLAB/RADA'' directory there are plenty of examples of how Paul Uhing compared simulation to test data. Generally you should grate a ''.m'' file with the same name as the log file this data was extracted from with _plot appended to the name. Generally you can just copy an for RADA_LQG_compPID_plot.m RADA_PID_compLQG_plot.m, RADA_LQG_sep_plot.m, or RADA_LQG_sep_ol_plot.m files and rename the structures for your test. These files create four figures. Figure 1 plots compares the x velocity data in the first sub figure and compares pitch (theta) data in the second sub figure. Figure 2 does the same thing as Figure 1 but with y velocity and roll data. Figure 3 looks at the yaw data. Finally, Figure 4 looks at the sample period between UAV and ERIS packets from the camera system just to check for periods of time with large packet drops. You can follow a similar pattern to compare motor commands. Just make sure that you compare Quad Motor 2 from the test data with Quad Motor 4 from simulation and vise versa because propellers 2 and 4 were switch in Eris's software compared to the Model. That is all you need to know for testing RADA against the model. e0c3b70e853d485b712343f2080c870d3dc77360 338 337 2016-09-21T23:31:22Z Jonessk 7 /* Setting up the Camera System */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. The initial setup and how to test the system can also be applied to demoing RADA. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging Batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supply because it is the only power supply that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} The YouTube video link above should explain how to use the charger. RADA currently uses three different Lithium polymer (Lipo) batteries: 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo for the propellers. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery voltage drops really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAh 4-cell generally charge in 10-20 minutes apiece while the 2600 mAh 2-cell generally take up to 70 minutes to charge fully. === Setting up the Camera System === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password (not posted here for security reasons, but any one who works in the lab should know it). Once logged in, look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should have the naming scheme ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by date modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in the main project screen arrange themselves like the camera system configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another popup window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They have the naming scheme ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackables are open, the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation, left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need to check to make sure the system is zeroed. #Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't, the front is the side opposite the switches and the side with the trackable constellation on it. #Make sure that the motor with the red motor mount is also facing the wall with the white boards. #Make sure the quad system is aligned along Eris Axis by standing behind the system. If the system is aligned, you should be able to block the mounting bolts of the front propeller motor with the pole while facing the east wall. #While holding the pendulum approximately vertical, see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. #Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and within a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise, go to the next step. #You need to zero the pendulum. ##Align ERIS so it is near zero yaw first (eye ball it). ##Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directions and hold it there. ##With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation'' button ##Now your friend can set the pendulum down and you can zero ERIS the same way. #Save the new trackable orientation by going to ''File->Save Trackables...'' and save a file using the same naming conventions as the trackable file you opened earlier. Use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use (the password isn't put here for security reasons). First, ensure that the RADA software is setup correctly for the test you want to run. To do this, you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below are compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also causes the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propellers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by an LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to accelerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packet drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA Senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have found that even on a good strt the ''[ok]'' messages will still print. === Turning on RADA === Turning on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the switches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you use EITHER the WIFI adapter OR hardwired Ethernet, because the VRPN may listen to the camera data broadcast over both connections which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in, you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection. in a commands prompt, not the one you compile the code from so that you can recompile for different setup without needing to close the connection. If you are using a WIFI connection use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connection use the command ''ssh root@192.168.0.54''. If the connection goes though you should be prompted for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the First Test After Power Up === For the first test after powering on Eris, a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect to the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell script will setup the NFS, and load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject'' and runs the executable. Once the user exits the executable, the log file produced is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see a warning that when copying the log file Eris couldn't maintain the file permission settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This date stamp uses the date on Eris, which is currently in June of 2008 as of August 2nd, 2016. Before starting the test, it is best to have someone spotting the pendulum and holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once the spotter is ready, run the shell script by using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA. You will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after startup you don't need to run this script. See the Section about Running additional tests below.r [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode you can use the following commands to enter the desired mode with a three second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode, this will only really work when using PIDs to control the pendulum. -''b'' : Enter Robot control mode, in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode, where the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file incase odd things happen somewhere. This just increments a counter so if you use it look for changes in the marker value. ==== Robot Control Model ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box set mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use he same commands as Tuning Mode. === Running additional Tests === Once you have run one test with Eris on it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_stat_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result it is ready to test much quicker. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and retrieving log files === If you are only demoing the system there is no need to go beyond this point. Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files are named like ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful of describing what the test was of or for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring battery voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there isn't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log is the headder. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value latter. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== 1. After test disconnect wheel battery from the system. 2. Measure voltage of battery using multimeter. [[Image:MeasureVwheel.jpg|800px]] You can use the plug used for charging the 2-cell Lipos but make sure to connect the plug to the multimeter before connecting the battery and disconnect the battery before disconnecting the plug from the mulitmeter. It is generally the best practice to give the multimeter a few minutes to allow for the voltage measurement to stabilize as the battery measurement tends to be a little low right after the test. The multimeter will report data out to four decimal places it is best just to round to three decimal places for the wheel voltage. ==== Quad Battery ==== 1. Setup code to run all four propellers at 50% throttle, uncomment the definition of ''mot50'' in main.cpp and compile the project. 2. Power off propellers by turning off the switch to the ESCs. 3. Connect multimeter to measure the voltage across one of the ESCs. This is done by using the power splitter cord. -Connect one of the female XT60 connectors on the splitter to a male XT60 connector to banana connector cable. -The banana connector connect to the hand held multimeter. The multimeter should be set to the 20VDC measurement setting. -Next unplug one the ESCs' power connection. -reconnect the ESC to power through the two remain connectors on the spliter cable. 4. Power on the propellers. 5. Run the system at 50% throttle and measure the steady-state voltage during the test. The battery will slow the voltage decay significantly, meaning it will keep the same measurement for a few seconds. 6. Stop the test and record the voltage in the log file. Make sure to disconnect the batter before removing the splitter cable. {| class="wikitable" style="text-align:center" |- | [[Image:PowerSplitter.jpg|200px]] | [[Image:QuadMultiCon.jpg |200px]] | [[Image:QuadMultiSet.JPG |200px]] | [[Image:QuadMeasESCcon.JPG|200px]] |- | Splitter cord. | Connect splitter to multimeter. | Settings for multimeter. | Connecting ESC through splitter. |} The testing setup should look like the image below: [[Image:QuadBattMeas.jpg|800px]] == Post processing and Simulation == Simulating a test of RADA starts with processing and storing the data. Then all of the parameters of the model are loaded in the MATLAB Workspace. Finally the Simulink file used for the simulation is opened and the length of the simulation is set to match the length of the actual test. The simulation is run and the simulation output is stored. Finally the data should be plotted and compared. === Using the MATLAB data parsing tool === In depth discussion of how to use the log file parsing tool is described [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] I suggest using the version of the tool in the rada_resarch_project git repository Paul Uhing used for his Master's research. It con be found on CO3050-11 under the ucart account in the directory ''~/rada_research_project/DataAnalysiTool_omnicoor/Tool''. Simply open MATLAB and set the working directory to this file path. In the MATLAB Command Prompt run ''DataAnalysis''. A popup window should open up. Select the log file you want to process and wait for the tool to finish processing the file. Once this is complete there should be four structures in the MATLAB workspace. -'''main''' : This contains all of the data extracted from the log file and the processing parameters used. main.expData contains two time structures: Time is used for the pendulum data and Eris_time is used for the ground vehicle data. -'''X_ref''' : This contains the reference vector in m/s for x velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Y_ref''' : This contains the reference vector in m/s for y velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Yaw_ref''' : This contains the reference vector in radians for yaw that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. This one is new incase people start testing the system with heading changes but is not used in the current setup. The first thing you should do is rename the main structure to the name you used for the log file. This is helpful for comparing multiple tests. Next you will want to crate two new variable ''Vquad_test'' an Vw_test''. In the MATLAB Command Prompt set the measured propeller voltage from the log file to ''Vquad_test'' and set the measured the wheel voltage to ''Vw_test'' as this will be used by the simulation. Finally if you did an open-loop test of the wheels create the variable ''Uol'' and set it to the open-loop wheel command used. Save all of these variables from the MATLAB workspace to a ''.mat'' file of the same name as log file you extracted the data from and save it in the same directory as your RADA Simulink files. As of August 2nd, 2016 this directory is ''~/rada_research_project/MATLAB/RADA.'' === Setting up the MATLAB workspace for simulation === Change your MATLAB directory to this directory. Then run the simulation setup files. Currently you just need to run ''modelParams_smallWheels_RADA'' in the MATLAB Command Prompt. Next open the Simulink file with that contains the model of RADA controlled by the controller you tested. -'''RADA_psiCtrl_v2_lqi_est.slx''' contains LQI, LQI+estimation, and LQG controller simulations. -'''RADA_psiCtrl_v2.slx''' contains the PID controlled system. -'''RADA_psiCtrl_v2_LQGsep.slx''' contains the subsystem LQG controlled system. -'''RADA_psiCtrl_v2_LQGsep_ol.slx''' contains the simulation of the pendulum system controlled by an LQG and Eris controlled with open-loop commands. Note all of the current (August 2nd, 2016) ''.slx'' files were created in MATLAB 2014b and will only work in MATLAB 2014B or newer. Then in the MATLAB Command Prompt type ''X_ref.time(end)'' exactly, don't add a semicolon, and hit enter. MATLAB will print the time of the last command in the X_ref structure. Set the en time of the simulation to this value and save your Simulink file. === Running simulations and storing results === Before running the simulation make sure that the simuation is using the ''ode23t'' differential equations solver. This system is a moderately stiff system of differential and the ''ode45'' solver doesn't do well with these types of systems. When using ''ode23t'' is should only take a few minutes to run a 100+ second simulation while doing the same test using ''ode45'' could take 8 hours. While this slow it is also bad for your hard drive as the simulation has to page between RAM and your computers hard drive a lot. Once this check is done run the simulation. While it is running check what the output structures variables are named for for your RADA test system. Once the simulation is done go to your MATLAB Workspace and select all 15 outputs for your simulation or your sub-simulation if you used '''RADA_psiCtrl_v2_lqi_est.slx'''. Save these 15 output structures to a ''.mat'' file named as the log file with _sim appended to the end of the name. The 15 outputs are structures containing a time vector and then the data from the simulation sampled at 100 Hz and the units of this data are the SI units (ex: radians, m/s). There is one output structure for x velocity, y velocity, x body velocity, y body velocity, theta (pitch), phi (roll), psi (yaw), and one per actuator command (ex: the command sent to a wheel). Now you have all the data you can plot it. === Plotting results === If you look at the ''DataSets'' folder below ''~/rada_research_project/MATLAB/RADA'' directory there are plenty of examples of how Paul Uhing compared simulation to test data. Generally you should grate a ''.m'' file with the same name as the log file this data was extracted from with _plot appended to the name. Generally you can just copy an for RADA_LQG_compPID_plot.m RADA_PID_compLQG_plot.m, RADA_LQG_sep_plot.m, or RADA_LQG_sep_ol_plot.m files and rename the structures for your test. These files create four figures. Figure 1 plots compares the x velocity data in the first sub figure and compares pitch (theta) data in the second sub figure. Figure 2 does the same thing as Figure 1 but with y velocity and roll data. Figure 3 looks at the yaw data. Finally, Figure 4 looks at the sample period between UAV and ERIS packets from the camera system just to check for periods of time with large packet drops. You can follow a similar pattern to compare motor commands. Just make sure that you compare Quad Motor 2 from the test data with Quad Motor 4 from simulation and vise versa because propellers 2 and 4 were switch in Eris's software compared to the Model. That is all you need to know for testing RADA against the model. 4fc976173e5a88c6e8cdb555506741bde4dbfdda 339 338 2016-09-21T23:35:51Z Jonessk 7 /* Connecting to RADA */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. The initial setup and how to test the system can also be applied to demoing RADA. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging Batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supply because it is the only power supply that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} The YouTube video link above should explain how to use the charger. RADA currently uses three different Lithium polymer (Lipo) batteries: 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo for the propellers. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery voltage drops really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAh 4-cell generally charge in 10-20 minutes apiece while the 2600 mAh 2-cell generally take up to 70 minutes to charge fully. === Setting up the Camera System === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password (not posted here for security reasons, but any one who works in the lab should know it). Once logged in, look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should have the naming scheme ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by date modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in the main project screen arrange themselves like the camera system configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another popup window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They have the naming scheme ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackables are open, the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation, left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need to check to make sure the system is zeroed. #Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't, the front is the side opposite the switches and the side with the trackable constellation on it. #Make sure that the motor with the red motor mount is also facing the wall with the white boards. #Make sure the quad system is aligned along Eris Axis by standing behind the system. If the system is aligned, you should be able to block the mounting bolts of the front propeller motor with the pole while facing the east wall. #While holding the pendulum approximately vertical, see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. #Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and within a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise, go to the next step. #You need to zero the pendulum. ##Align ERIS so it is near zero yaw first (eye ball it). ##Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directions and hold it there. ##With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation'' button ##Now your friend can set the pendulum down and you can zero ERIS the same way. #Save the new trackable orientation by going to ''File->Save Trackables...'' and save a file using the same naming conventions as the trackable file you opened earlier. Use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use (the password isn't put here for security reasons). First, ensure that the RADA software is setup correctly for the test you want to run. To do this, you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below are compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also causes the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propellers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by an LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to accelerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packet drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA Senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have found that even on a good strt the ''[ok]'' messages will still print. === Turning on RADA === Turning on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the switches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you use EITHER the WIFI adapter OR hardwired Ethernet, because the VRPN may listen to the camera data broadcast over both connections which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in, you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection in a command prompt. This is not the one you compile the code from so that you can recompile for different setup without needing to close the connection. If you are using a WIFI connection, use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connection use the command ''ssh root@192.168.0.54''. If the connection goes though you should be prompted for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the First Test After Power Up === For the first test after powering on Eris, a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect to the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell script will setup the NFS, and load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject'' and runs the executable. Once the user exits the executable, the log file produced is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see a warning that when copying the log file Eris couldn't maintain the file permission settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This date stamp uses the date on Eris, which is currently in June of 2008 as of August 2nd, 2016. Before starting the test, it is best to have someone spotting the pendulum and holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once the spotter is ready, run the shell script by using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA. You will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after startup you don't need to run this script. See the Section about Running additional tests below.r [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode you can use the following commands to enter the desired mode with a three second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode, this will only really work when using PIDs to control the pendulum. -''b'' : Enter Robot control mode, in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode, where the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file incase odd things happen somewhere. This just increments a counter so if you use it look for changes in the marker value. ==== Robot Control Model ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box set mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use he same commands as Tuning Mode. === Running additional Tests === Once you have run one test with Eris on it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_stat_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result it is ready to test much quicker. Before starting the test it is best to have someone spotting the pendulum a holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always run ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell scrip by= using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and retrieving log files === If you are only demoing the system there is no need to go beyond this point. Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files are named like ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful of describing what the test was of or for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring battery voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there isn't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log is the headder. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value latter. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== 1. After test disconnect wheel battery from the system. 2. Measure voltage of battery using multimeter. [[Image:MeasureVwheel.jpg|800px]] You can use the plug used for charging the 2-cell Lipos but make sure to connect the plug to the multimeter before connecting the battery and disconnect the battery before disconnecting the plug from the mulitmeter. It is generally the best practice to give the multimeter a few minutes to allow for the voltage measurement to stabilize as the battery measurement tends to be a little low right after the test. The multimeter will report data out to four decimal places it is best just to round to three decimal places for the wheel voltage. ==== Quad Battery ==== 1. Setup code to run all four propellers at 50% throttle, uncomment the definition of ''mot50'' in main.cpp and compile the project. 2. Power off propellers by turning off the switch to the ESCs. 3. Connect multimeter to measure the voltage across one of the ESCs. This is done by using the power splitter cord. -Connect one of the female XT60 connectors on the splitter to a male XT60 connector to banana connector cable. -The banana connector connect to the hand held multimeter. The multimeter should be set to the 20VDC measurement setting. -Next unplug one the ESCs' power connection. -reconnect the ESC to power through the two remain connectors on the spliter cable. 4. Power on the propellers. 5. Run the system at 50% throttle and measure the steady-state voltage during the test. The battery will slow the voltage decay significantly, meaning it will keep the same measurement for a few seconds. 6. Stop the test and record the voltage in the log file. Make sure to disconnect the batter before removing the splitter cable. {| class="wikitable" style="text-align:center" |- | [[Image:PowerSplitter.jpg|200px]] | [[Image:QuadMultiCon.jpg |200px]] | [[Image:QuadMultiSet.JPG |200px]] | [[Image:QuadMeasESCcon.JPG|200px]] |- | Splitter cord. | Connect splitter to multimeter. | Settings for multimeter. | Connecting ESC through splitter. |} The testing setup should look like the image below: [[Image:QuadBattMeas.jpg|800px]] == Post processing and Simulation == Simulating a test of RADA starts with processing and storing the data. Then all of the parameters of the model are loaded in the MATLAB Workspace. Finally the Simulink file used for the simulation is opened and the length of the simulation is set to match the length of the actual test. The simulation is run and the simulation output is stored. Finally the data should be plotted and compared. === Using the MATLAB data parsing tool === In depth discussion of how to use the log file parsing tool is described [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] I suggest using the version of the tool in the rada_resarch_project git repository Paul Uhing used for his Master's research. It con be found on CO3050-11 under the ucart account in the directory ''~/rada_research_project/DataAnalysiTool_omnicoor/Tool''. Simply open MATLAB and set the working directory to this file path. In the MATLAB Command Prompt run ''DataAnalysis''. A popup window should open up. Select the log file you want to process and wait for the tool to finish processing the file. Once this is complete there should be four structures in the MATLAB workspace. -'''main''' : This contains all of the data extracted from the log file and the processing parameters used. main.expData contains two time structures: Time is used for the pendulum data and Eris_time is used for the ground vehicle data. -'''X_ref''' : This contains the reference vector in m/s for x velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Y_ref''' : This contains the reference vector in m/s for y velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Yaw_ref''' : This contains the reference vector in radians for yaw that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. This one is new incase people start testing the system with heading changes but is not used in the current setup. The first thing you should do is rename the main structure to the name you used for the log file. This is helpful for comparing multiple tests. Next you will want to crate two new variable ''Vquad_test'' an Vw_test''. In the MATLAB Command Prompt set the measured propeller voltage from the log file to ''Vquad_test'' and set the measured the wheel voltage to ''Vw_test'' as this will be used by the simulation. Finally if you did an open-loop test of the wheels create the variable ''Uol'' and set it to the open-loop wheel command used. Save all of these variables from the MATLAB workspace to a ''.mat'' file of the same name as log file you extracted the data from and save it in the same directory as your RADA Simulink files. As of August 2nd, 2016 this directory is ''~/rada_research_project/MATLAB/RADA.'' === Setting up the MATLAB workspace for simulation === Change your MATLAB directory to this directory. Then run the simulation setup files. Currently you just need to run ''modelParams_smallWheels_RADA'' in the MATLAB Command Prompt. Next open the Simulink file with that contains the model of RADA controlled by the controller you tested. -'''RADA_psiCtrl_v2_lqi_est.slx''' contains LQI, LQI+estimation, and LQG controller simulations. -'''RADA_psiCtrl_v2.slx''' contains the PID controlled system. -'''RADA_psiCtrl_v2_LQGsep.slx''' contains the subsystem LQG controlled system. -'''RADA_psiCtrl_v2_LQGsep_ol.slx''' contains the simulation of the pendulum system controlled by an LQG and Eris controlled with open-loop commands. Note all of the current (August 2nd, 2016) ''.slx'' files were created in MATLAB 2014b and will only work in MATLAB 2014B or newer. Then in the MATLAB Command Prompt type ''X_ref.time(end)'' exactly, don't add a semicolon, and hit enter. MATLAB will print the time of the last command in the X_ref structure. Set the en time of the simulation to this value and save your Simulink file. === Running simulations and storing results === Before running the simulation make sure that the simuation is using the ''ode23t'' differential equations solver. This system is a moderately stiff system of differential and the ''ode45'' solver doesn't do well with these types of systems. When using ''ode23t'' is should only take a few minutes to run a 100+ second simulation while doing the same test using ''ode45'' could take 8 hours. While this slow it is also bad for your hard drive as the simulation has to page between RAM and your computers hard drive a lot. Once this check is done run the simulation. While it is running check what the output structures variables are named for for your RADA test system. Once the simulation is done go to your MATLAB Workspace and select all 15 outputs for your simulation or your sub-simulation if you used '''RADA_psiCtrl_v2_lqi_est.slx'''. Save these 15 output structures to a ''.mat'' file named as the log file with _sim appended to the end of the name. The 15 outputs are structures containing a time vector and then the data from the simulation sampled at 100 Hz and the units of this data are the SI units (ex: radians, m/s). There is one output structure for x velocity, y velocity, x body velocity, y body velocity, theta (pitch), phi (roll), psi (yaw), and one per actuator command (ex: the command sent to a wheel). Now you have all the data you can plot it. === Plotting results === If you look at the ''DataSets'' folder below ''~/rada_research_project/MATLAB/RADA'' directory there are plenty of examples of how Paul Uhing compared simulation to test data. Generally you should grate a ''.m'' file with the same name as the log file this data was extracted from with _plot appended to the name. Generally you can just copy an for RADA_LQG_compPID_plot.m RADA_PID_compLQG_plot.m, RADA_LQG_sep_plot.m, or RADA_LQG_sep_ol_plot.m files and rename the structures for your test. These files create four figures. Figure 1 plots compares the x velocity data in the first sub figure and compares pitch (theta) data in the second sub figure. Figure 2 does the same thing as Figure 1 but with y velocity and roll data. Figure 3 looks at the yaw data. Finally, Figure 4 looks at the sample period between UAV and ERIS packets from the camera system just to check for periods of time with large packet drops. You can follow a similar pattern to compare motor commands. Just make sure that you compare Quad Motor 2 from the test data with Quad Motor 4 from simulation and vise versa because propellers 2 and 4 were switch in Eris's software compared to the Model. That is all you need to know for testing RADA against the model. 7a58f6f4d227d60dc7a63cb9eea8039f861024b7 340 339 2016-09-21T23:51:49Z Jonessk 7 /* Testing RADA */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. The initial setup and how to test the system can also be applied to demoing RADA. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging Batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supply because it is the only power supply that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} The YouTube video link above should explain how to use the charger. RADA currently uses three different Lithium polymer (Lipo) batteries: 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo for the propellers. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery voltage drops really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAh 4-cell generally charge in 10-20 minutes apiece while the 2600 mAh 2-cell generally take up to 70 minutes to charge fully. === Setting up the Camera System === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password (not posted here for security reasons, but any one who works in the lab should know it). Once logged in, look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should have the naming scheme ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by date modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in the main project screen arrange themselves like the camera system configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another popup window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They have the naming scheme ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackables are open, the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation, left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need to check to make sure the system is zeroed. #Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't, the front is the side opposite the switches and the side with the trackable constellation on it. #Make sure that the motor with the red motor mount is also facing the wall with the white boards. #Make sure the quad system is aligned along Eris Axis by standing behind the system. If the system is aligned, you should be able to block the mounting bolts of the front propeller motor with the pole while facing the east wall. #While holding the pendulum approximately vertical, see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. #Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and within a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise, go to the next step. #You need to zero the pendulum. ##Align ERIS so it is near zero yaw first (eye ball it). ##Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directions and hold it there. ##With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation'' button ##Now your friend can set the pendulum down and you can zero ERIS the same way. #Save the new trackable orientation by going to ''File->Save Trackables...'' and save a file using the same naming conventions as the trackable file you opened earlier. Use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use (the password isn't put here for security reasons). First, ensure that the RADA software is setup correctly for the test you want to run. To do this, you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below are compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also causes the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propellers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by an LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to accelerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packet drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA Senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have found that even on a good strt the ''[ok]'' messages will still print. === Turning on RADA === Turning on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the switches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you use EITHER the WIFI adapter OR hardwired Ethernet, because the VRPN may listen to the camera data broadcast over both connections which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in, you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection in a command prompt. This is not the one you compile the code from so that you can recompile for different setup without needing to close the connection. If you are using a WIFI connection, use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connection use the command ''ssh root@192.168.0.54''. If the connection goes though you should be prompted for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the First Test After Power Up === For the first test after powering on Eris, a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect to the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell script will setup the NFS, and load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject'' and runs the executable. Once the user exits the executable, the log file produced is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist, it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see a warning that when copying the log file Eris couldn't maintain the file permission settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This date stamp uses the date on Eris, which is currently in June of 2008 as of August 2nd, 2016. Before starting the test, it is best to have someone spotting the pendulum and holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once the spotter is ready, run the shell script by using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA. You will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after startup you don't need to run this script. See the Section about Running additional tests below.r [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally, you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode, you can use the following commands to enter the desired mode with a three-second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode - this will only really work when using PIDs to control the pendulum. -''b'' : Enter robot control mode - in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode - the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file in case odd things happen somewhere. This just increments a counter, so if you use it, look for changes in the marker value. ==== Robot Control Mode ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box step mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use the same commands as Tuning Mode. === Running Additional Tests === Once you have run one test with Eris on, it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_start_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result, it is ready to test much quicker. Before starting the test, it is best to have someone spotting the pendulum and holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell script by using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and Retrieving Log Files === If you are only demoing the system, there is no need to go beyond this point. Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files have the naming scheme ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful for describing what the test was conducted for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring Battery Voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there aren't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log are the header. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value later. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== #After test disconnect wheel battery from the system. #Measure voltage of battery using multimeter. [[Image:MeasureVwheel.jpg|800px]] You can use the plug used for charging the 2-cell Lipos but make sure to connect the plug to the multimeter before connecting the battery and disconnect the battery before disconnecting the plug from the mulitmeter. It is generally the best practice to give the multimeter a few minutes to allow for the voltage measurement to stabilize as the battery measurement tends to be a little low right after the test. The multimeter will report data out to four decimal places it is best just to round to three decimal places for the wheel voltage. ==== Propeller Battery ==== #Setup code to run all four propellers at 50% throttle, uncomment the definition of ''mot50'' in main.cpp and compile the project. #Power off propellers by turning off the switch to the ESCs. #Connect multimeter to measure the voltage across one of the ESCs. This is done by using the power splitter cord. ##Connect one of the female XT60 connectors on the splitter to a male XT60 connector to banana connector cable. ##The banana connector connects to the hand held multimeter. The multimeter should be set to the 20VDC measurement setting. ##Next unplug one the ESCs' power connection. ##Reconnect the ESC to power through the two remain connectors on the splitter cable. #Power on the propellers. #Run the system at 50% throttle and measure the steady-state voltage during the test. The battery will slow the voltage decay significantly, meaning it will keep the same measurement for a few seconds. #Stop the test and record the voltage in the log file. Make sure to disconnect the battery before removing the splitter cable. {| class="wikitable" style="text-align:center" |- | [[Image:PowerSplitter.jpg|200px]] | [[Image:QuadMultiCon.jpg |200px]] | [[Image:QuadMultiSet.JPG |200px]] | [[Image:QuadMeasESCcon.JPG|200px]] |- | Splitter cord. | Connect splitter to multimeter. | Settings for multimeter. | Connecting ESC through splitter. |} The testing setup should look like the image below: [[Image:QuadBattMeas.jpg|800px]] == Post processing and Simulation == Simulating a test of RADA starts with processing and storing the data. Then all of the parameters of the model are loaded in the MATLAB Workspace. Finally the Simulink file used for the simulation is opened and the length of the simulation is set to match the length of the actual test. The simulation is run and the simulation output is stored. Finally the data should be plotted and compared. === Using the MATLAB data parsing tool === In depth discussion of how to use the log file parsing tool is described [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] I suggest using the version of the tool in the rada_resarch_project git repository Paul Uhing used for his Master's research. It con be found on CO3050-11 under the ucart account in the directory ''~/rada_research_project/DataAnalysiTool_omnicoor/Tool''. Simply open MATLAB and set the working directory to this file path. In the MATLAB Command Prompt run ''DataAnalysis''. A popup window should open up. Select the log file you want to process and wait for the tool to finish processing the file. Once this is complete there should be four structures in the MATLAB workspace. -'''main''' : This contains all of the data extracted from the log file and the processing parameters used. main.expData contains two time structures: Time is used for the pendulum data and Eris_time is used for the ground vehicle data. -'''X_ref''' : This contains the reference vector in m/s for x velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Y_ref''' : This contains the reference vector in m/s for y velocity that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Yaw_ref''' : This contains the reference vector in radians for yaw that is feed into Simulink. This expedites the simulation setup process, this used to be done by hand. This one is new incase people start testing the system with heading changes but is not used in the current setup. The first thing you should do is rename the main structure to the name you used for the log file. This is helpful for comparing multiple tests. Next you will want to crate two new variable ''Vquad_test'' an Vw_test''. In the MATLAB Command Prompt set the measured propeller voltage from the log file to ''Vquad_test'' and set the measured the wheel voltage to ''Vw_test'' as this will be used by the simulation. Finally if you did an open-loop test of the wheels create the variable ''Uol'' and set it to the open-loop wheel command used. Save all of these variables from the MATLAB workspace to a ''.mat'' file of the same name as log file you extracted the data from and save it in the same directory as your RADA Simulink files. As of August 2nd, 2016 this directory is ''~/rada_research_project/MATLAB/RADA.'' === Setting up the MATLAB workspace for simulation === Change your MATLAB directory to this directory. Then run the simulation setup files. Currently you just need to run ''modelParams_smallWheels_RADA'' in the MATLAB Command Prompt. Next open the Simulink file with that contains the model of RADA controlled by the controller you tested. -'''RADA_psiCtrl_v2_lqi_est.slx''' contains LQI, LQI+estimation, and LQG controller simulations. -'''RADA_psiCtrl_v2.slx''' contains the PID controlled system. -'''RADA_psiCtrl_v2_LQGsep.slx''' contains the subsystem LQG controlled system. -'''RADA_psiCtrl_v2_LQGsep_ol.slx''' contains the simulation of the pendulum system controlled by an LQG and Eris controlled with open-loop commands. Note all of the current (August 2nd, 2016) ''.slx'' files were created in MATLAB 2014b and will only work in MATLAB 2014B or newer. Then in the MATLAB Command Prompt type ''X_ref.time(end)'' exactly, don't add a semicolon, and hit enter. MATLAB will print the time of the last command in the X_ref structure. Set the en time of the simulation to this value and save your Simulink file. === Running simulations and storing results === Before running the simulation make sure that the simuation is using the ''ode23t'' differential equations solver. This system is a moderately stiff system of differential and the ''ode45'' solver doesn't do well with these types of systems. When using ''ode23t'' is should only take a few minutes to run a 100+ second simulation while doing the same test using ''ode45'' could take 8 hours. While this slow it is also bad for your hard drive as the simulation has to page between RAM and your computers hard drive a lot. Once this check is done run the simulation. While it is running check what the output structures variables are named for for your RADA test system. Once the simulation is done go to your MATLAB Workspace and select all 15 outputs for your simulation or your sub-simulation if you used '''RADA_psiCtrl_v2_lqi_est.slx'''. Save these 15 output structures to a ''.mat'' file named as the log file with _sim appended to the end of the name. The 15 outputs are structures containing a time vector and then the data from the simulation sampled at 100 Hz and the units of this data are the SI units (ex: radians, m/s). There is one output structure for x velocity, y velocity, x body velocity, y body velocity, theta (pitch), phi (roll), psi (yaw), and one per actuator command (ex: the command sent to a wheel). Now you have all the data you can plot it. === Plotting results === If you look at the ''DataSets'' folder below ''~/rada_research_project/MATLAB/RADA'' directory there are plenty of examples of how Paul Uhing compared simulation to test data. Generally you should grate a ''.m'' file with the same name as the log file this data was extracted from with _plot appended to the name. Generally you can just copy an for RADA_LQG_compPID_plot.m RADA_PID_compLQG_plot.m, RADA_LQG_sep_plot.m, or RADA_LQG_sep_ol_plot.m files and rename the structures for your test. These files create four figures. Figure 1 plots compares the x velocity data in the first sub figure and compares pitch (theta) data in the second sub figure. Figure 2 does the same thing as Figure 1 but with y velocity and roll data. Figure 3 looks at the yaw data. Finally, Figure 4 looks at the sample period between UAV and ERIS packets from the camera system just to check for periods of time with large packet drops. You can follow a similar pattern to compare motor commands. Just make sure that you compare Quad Motor 2 from the test data with Quad Motor 4 from simulation and vise versa because propellers 2 and 4 were switch in Eris's software compared to the Model. That is all you need to know for testing RADA against the model. 9a5391308e212c9f324dafa2b6f7c87881ffeb52 341 340 2016-09-22T00:05:12Z Jonessk 7 /* Post processing and Simulation */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. The initial setup and how to test the system can also be applied to demoing RADA. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging Batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supply because it is the only power supply that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} The YouTube video link above should explain how to use the charger. RADA currently uses three different Lithium polymer (Lipo) batteries: 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo for the propellers. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery voltage drops really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAh 4-cell generally charge in 10-20 minutes apiece while the 2600 mAh 2-cell generally take up to 70 minutes to charge fully. === Setting up the Camera System === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password (not posted here for security reasons, but any one who works in the lab should know it). Once logged in, look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should have the naming scheme ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by date modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in the main project screen arrange themselves like the camera system configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another popup window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They have the naming scheme ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackables are open, the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation, left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. This gives the orientation in the wrong order for how we currently use the Euler angles. When two or three of the angles are near zero you can switch yaw and pitch to get roughly the correct orientation. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need to check to make sure the system is zeroed. #Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't, the front is the side opposite the switches and the side with the trackable constellation on it. #Make sure that the motor with the red motor mount is also facing the wall with the white boards. #Make sure the quad system is aligned along Eris Axis by standing behind the system. If the system is aligned, you should be able to block the mounting bolts of the front propeller motor with the pole while facing the east wall. #While holding the pendulum approximately vertical, see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. #Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and within a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise, go to the next step. #You need to zero the pendulum. ##Align ERIS so it is near zero yaw first (eye ball it). ##Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directions and hold it there. ##With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation'' button ##Now your friend can set the pendulum down and you can zero ERIS the same way. #Save the new trackable orientation by going to ''File->Save Trackables...'' and save a file using the same naming conventions as the trackable file you opened earlier. Use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use (the password isn't put here for security reasons). First, ensure that the RADA software is setup correctly for the test you want to run. To do this, you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below are compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also causes the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propellers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by an LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to accelerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packet drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA Senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have found that even on a good strt the ''[ok]'' messages will still print. === Turning on RADA === Turning on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the switches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you use EITHER the WIFI adapter OR hardwired Ethernet, because the VRPN may listen to the camera data broadcast over both connections which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in, you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection in a command prompt. This is not the one you compile the code from so that you can recompile for different setup without needing to close the connection. If you are using a WIFI connection, use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connection use the command ''ssh root@192.168.0.54''. If the connection goes though you should be prompted for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the First Test After Power Up === For the first test after powering on Eris, a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect to the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell script will setup the NFS, and load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject'' and runs the executable. Once the user exits the executable, the log file produced is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist, it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see a warning that when copying the log file Eris couldn't maintain the file permission settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This date stamp uses the date on Eris, which is currently in June of 2008 as of August 2nd, 2016. Before starting the test, it is best to have someone spotting the pendulum and holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once the spotter is ready, run the shell script by using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA. You will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after startup you don't need to run this script. See the Section about Running additional tests below.r [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally, you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode, you can use the following commands to enter the desired mode with a three-second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode - this will only really work when using PIDs to control the pendulum. -''b'' : Enter robot control mode - in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode - the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file in case odd things happen somewhere. This just increments a counter, so if you use it, look for changes in the marker value. ==== Robot Control Mode ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box step mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use the same commands as Tuning Mode. === Running Additional Tests === Once you have run one test with Eris on, it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_start_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result, it is ready to test much quicker. Before starting the test, it is best to have someone spotting the pendulum and holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell script by using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and Retrieving Log Files === If you are only demoing the system, there is no need to go beyond this point. Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files have the naming scheme ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful for describing what the test was conducted for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring Battery Voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there aren't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log are the header. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value later. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== #After test disconnect wheel battery from the system. #Measure voltage of battery using multimeter. [[Image:MeasureVwheel.jpg|800px]] You can use the plug used for charging the 2-cell Lipos but make sure to connect the plug to the multimeter before connecting the battery and disconnect the battery before disconnecting the plug from the mulitmeter. It is generally the best practice to give the multimeter a few minutes to allow for the voltage measurement to stabilize as the battery measurement tends to be a little low right after the test. The multimeter will report data out to four decimal places it is best just to round to three decimal places for the wheel voltage. ==== Propeller Battery ==== #Setup code to run all four propellers at 50% throttle, uncomment the definition of ''mot50'' in main.cpp and compile the project. #Power off propellers by turning off the switch to the ESCs. #Connect multimeter to measure the voltage across one of the ESCs. This is done by using the power splitter cord. ##Connect one of the female XT60 connectors on the splitter to a male XT60 connector to banana connector cable. ##The banana connector connects to the hand held multimeter. The multimeter should be set to the 20VDC measurement setting. ##Next unplug one the ESCs' power connection. ##Reconnect the ESC to power through the two remain connectors on the splitter cable. #Power on the propellers. #Run the system at 50% throttle and measure the steady-state voltage during the test. The battery will slow the voltage decay significantly, meaning it will keep the same measurement for a few seconds. #Stop the test and record the voltage in the log file. Make sure to disconnect the battery before removing the splitter cable. {| class="wikitable" style="text-align:center" |- | [[Image:PowerSplitter.jpg|200px]] | [[Image:QuadMultiCon.jpg |200px]] | [[Image:QuadMultiSet.JPG |200px]] | [[Image:QuadMeasESCcon.JPG|200px]] |- | Splitter cord. | Connect splitter to multimeter. | Settings for multimeter. | Connecting ESC through splitter. |} The testing setup should look like the image below: [[Image:QuadBattMeas.jpg|800px]] == Post Processing and Simulation == Simulating a test of RADA starts with processing and storing the data. Then all of the parameters of the model are loaded in the MATLAB Workspace. Next, the Simulink file used for the simulation is opened and the length of the simulation is set to match the length of the actual test. The simulation is run and the simulation output is stored. Finally, the data should be plotted and compared. === Using the MATLAB Data Parsing Tool === In-depth discussion of how to use the log file parsing tool is described [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] It is suggested to use the version of the tool in the rada_resarch_project git repository Paul Uhing used for his Master's research. It can be found on CO3050-11 under the ucart account in the directory ''~/rada_research_project/DataAnalysiTool_omnicoor/Tool''. Simply open MATLAB and set the working directory to this file path. In the MATLAB Command Prompt run ''DataAnalysis''. A popup window should open up. Select the log file you want to process and wait for the tool to finish processing the file. Once this is complete there should be four structures in the MATLAB workspace. -'''main''' : This contains all of the data extracted from the log file and the processing parameters used. main.expData contains two time structures: Time is used for the pendulum data and Eris_time is used for the ground vehicle data. -'''X_ref''' : This contains the reference vector in m/s for x velocity that is fed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Y_ref''' : This contains the reference vector in m/s for y velocity that is fed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Yaw_ref''' : This contains the reference vector in radians for yaw that is fed into Simulink. This expedites the simulation setup process, this used to be done by hand. This one is new in case people start testing the system with heading changes but is not used in the current setup. The first thing you should do is rename the main structure to the name you used for the log file. This is helpful for comparing multiple tests. Next, you will want to create two new variable ''Vquad_test'' and ''Vw_test''. In the MATLAB Command Prompt set the measured propeller voltage from the log file to ''Vquad_test'' and set the measured wheel voltage to ''Vw_test'' as this will be used by the simulation. Finally, if you did an open-loop test of the wheels create the variable ''Uol'' and set it to the open-loop wheel command used. Save all of these variables from the MATLAB workspace to a ''.mat'' file of the same name as the log file you extracted the data from and save it in the same directory as your RADA Simulink files. As of August 2nd, 2016 this directory is ''~/rada_research_project/MATLAB/RADA.'' === Setting up the MATLAB Workspace for Simulation === Change your MATLAB directory to this directory. Then run the simulation setup files. Currently, you only need to run ''modelParams_smallWheels_RADA'' in the MATLAB Command Prompt. Next, open the Simulink file that contains the model of RADA controlled by the controller you tested. -'''RADA_psiCtrl_v2_lqi_est.slx''' contains LQI, LQI+estimation, and LQG controller simulations. -'''RADA_psiCtrl_v2.slx''' contains the PID controlled system. -'''RADA_psiCtrl_v2_LQGsep.slx''' contains the subsystem LQG controlled system. -'''RADA_psiCtrl_v2_LQGsep_ol.slx''' contains the simulation of the pendulum system controlled by an LQG and Eris controlled with open-loop commands. Note all of the current (August 2nd, 2016) ''.slx'' files were created in MATLAB 2014b and will only work in MATLAB 2014b or newer. Then in the MATLAB Command Prompt type ''X_ref.time(end)'' exactly, don't add a semicolon, and hit enter. MATLAB will print the time of the last command in the X_ref structure. Set the end time of the simulation to this value and save your Simulink file. === Running Simulations and Storing Results === Before running the simulation make sure that the simulation is using the ''ode23t'' differential equations solver. This system is a moderately stiff system of differential and the ''ode45'' solver doesn't do well with these types of systems. When using ''ode23t'' is should only take a few minutes to run a 100+ second simulation while doing the same test using ''ode45'' could take 8 hours. While this is slow, it is also bad for your hard drive, as the simulation has to page between RAM and your computer's hard drive a lot. Once this check is done, run the simulation. While it is running, check what the output structures variables are named for your RADA test system. Once the simulation is done, go to your MATLAB Workspace and select all 15 outputs for your simulation or your sub-simulation if you used '''RADA_psiCtrl_v2_lqi_est.slx'''. Save these 15 output structures to a ''.mat'' file named as the log file with _sim appended to the end of the name. The 15 outputs are structures containing a time vector and then the data from the simulation sampled at 100 Hz and the units of this data are the SI units (ex: radians, m/s). There is one output structure for x velocity, y velocity, x body velocity, y body velocity, theta (pitch), phi (roll), psi (yaw), and one per actuator command (ex: the command sent to a wheel). Now you have all the data you can plot it. === Plotting Results === If you look at the ''DataSets'' folder below ''~/rada_research_project/MATLAB/RADA'' directory there are plenty of examples of how Paul Uhing compared simulation to test data. Generally, you should create an ''.m'' file with the same name as the log file this data was extracted from with _plot appended to the name. Generally you can just copy and paste for ''RADA_LQG_compPID_plot.m'', ''RADA_PID_compLQG_plot.m'', ''RADA_LQG_sep_plot.m'', or ''RADA_LQG_sep_ol_plot.m'' files and rename the structures for your test. These files create four figures. Figure 1 plots and compares the x velocity data in the first sub-figure and compares pitch (theta) data in the second sub-figure. Figure 2 does the same thing as Figure 1 but with y velocity and roll data. Figure 3 looks at the yaw data. Figure 4 looks at the sample period between UAV and ERIS packets from the camera system to check for periods of time with large packet drops. You can follow a similar pattern to compare motor commands. Make sure that you compare Quad Motor 2 from the test data with Quad Motor 4 from simulation and vice versa because propellers 2 and 4 were switched in Eris's software compared to the Model. That is all you need to know for testing RADA against the model. a709db0a20ef1a133b313425a2cf610d31e04d67 344 341 2016-09-26T18:38:15Z Pfuhing 5 /* Setting up the Camera System */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. The initial setup and how to test the system can also be applied to demoing RADA. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging Batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supply because it is the only power supply that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} The YouTube video link above should explain how to use the charger. RADA currently uses three different Lithium polymer (Lipo) batteries: 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo for the propellers. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery voltage drops really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAh 4-cell generally charge in 10-20 minutes apiece while the 2600 mAh 2-cell generally take up to 70 minutes to charge fully. === Setting up the Camera System === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password (not posted here for security reasons, but any one who works in the lab should know it). Once logged in, look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should have the naming scheme ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by date modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in the main project screen arrange themselves like the camera system configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another popup window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They have the naming scheme ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackables are open, the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation, left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. The orientation of the system represented by pitch, roll, and yaw Euler Angles. The Euler Angles orientation is determined by the order the angles are solved for determine the result. Tracking Tools doesn't use the same angle calculation order as RADA uses to calculate the system orientation so unless the pendulum is held near vertical the orientation given is not correct. General speaking if the system is held so that at least 2/3 angles are near zero you can approximate the orientation seen by the system by swapping the yaw a pitch angles shown by the real time information tab. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need to check to make sure the system is zeroed. #Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't, the front is the side opposite the switches and the side with the trackable constellation on it. #Make sure that the motor with the red motor mount is also facing the wall with the white boards. #Make sure the quad system is aligned along Eris Axis by standing behind the system. If the system is aligned, you should be able to block the mounting bolts of the front propeller motor with the pole while facing the east wall. #While holding the pendulum approximately vertical, see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. #Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and within a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise, go to the next step. #You need to zero the pendulum. ##Align ERIS so it is near zero yaw first (eye ball it). ##Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directions and hold it there. ##With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation'' button ##Now your friend can set the pendulum down and you can zero ERIS the same way. #Save the new trackable orientation by going to ''File->Save Trackables...'' and save a file using the same naming conventions as the trackable file you opened earlier. Use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use (the password isn't put here for security reasons). First, ensure that the RADA software is setup correctly for the test you want to run. To do this, you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below are compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by a tracking H2 controller. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will has the system to be controlled by an H2 contorller that contains propeller states. This also causes the system to "Dance." -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propellers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by an LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to accelerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packet drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA Senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have found that even on a good strt the ''[ok]'' messages will still print. === Turning on RADA === Turning on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the switches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you use EITHER the WIFI adapter OR hardwired Ethernet, because the VRPN may listen to the camera data broadcast over both connections which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in, you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection in a command prompt. This is not the one you compile the code from so that you can recompile for different setup without needing to close the connection. If you are using a WIFI connection, use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connection use the command ''ssh root@192.168.0.54''. If the connection goes though you should be prompted for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the First Test After Power Up === For the first test after powering on Eris, a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect to the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell script will setup the NFS, and load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject'' and runs the executable. Once the user exits the executable, the log file produced is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist, it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see a warning that when copying the log file Eris couldn't maintain the file permission settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This date stamp uses the date on Eris, which is currently in June of 2008 as of August 2nd, 2016. Before starting the test, it is best to have someone spotting the pendulum and holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once the spotter is ready, run the shell script by using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA. You will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after startup you don't need to run this script. See the Section about Running additional tests below.r [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally, you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode, you can use the following commands to enter the desired mode with a three-second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode - this will only really work when using PIDs to control the pendulum. -''b'' : Enter robot control mode - in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode - the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file in case odd things happen somewhere. This just increments a counter, so if you use it, look for changes in the marker value. ==== Robot Control Mode ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box step mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use the same commands as Tuning Mode. === Running Additional Tests === Once you have run one test with Eris on, it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_start_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result, it is ready to test much quicker. Before starting the test, it is best to have someone spotting the pendulum and holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell script by using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and Retrieving Log Files === If you are only demoing the system, there is no need to go beyond this point. Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files have the naming scheme ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful for describing what the test was conducted for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring Battery Voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there aren't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log are the header. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value later. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== #After test disconnect wheel battery from the system. #Measure voltage of battery using multimeter. [[Image:MeasureVwheel.jpg|800px]] You can use the plug used for charging the 2-cell Lipos but make sure to connect the plug to the multimeter before connecting the battery and disconnect the battery before disconnecting the plug from the mulitmeter. It is generally the best practice to give the multimeter a few minutes to allow for the voltage measurement to stabilize as the battery measurement tends to be a little low right after the test. The multimeter will report data out to four decimal places it is best just to round to three decimal places for the wheel voltage. ==== Propeller Battery ==== #Setup code to run all four propellers at 50% throttle, uncomment the definition of ''mot50'' in main.cpp and compile the project. #Power off propellers by turning off the switch to the ESCs. #Connect multimeter to measure the voltage across one of the ESCs. This is done by using the power splitter cord. ##Connect one of the female XT60 connectors on the splitter to a male XT60 connector to banana connector cable. ##The banana connector connects to the hand held multimeter. The multimeter should be set to the 20VDC measurement setting. ##Next unplug one the ESCs' power connection. ##Reconnect the ESC to power through the two remain connectors on the splitter cable. #Power on the propellers. #Run the system at 50% throttle and measure the steady-state voltage during the test. The battery will slow the voltage decay significantly, meaning it will keep the same measurement for a few seconds. #Stop the test and record the voltage in the log file. Make sure to disconnect the battery before removing the splitter cable. {| class="wikitable" style="text-align:center" |- | [[Image:PowerSplitter.jpg|200px]] | [[Image:QuadMultiCon.jpg |200px]] | [[Image:QuadMultiSet.JPG |200px]] | [[Image:QuadMeasESCcon.JPG|200px]] |- | Splitter cord. | Connect splitter to multimeter. | Settings for multimeter. | Connecting ESC through splitter. |} The testing setup should look like the image below: [[Image:QuadBattMeas.jpg|800px]] == Post Processing and Simulation == Simulating a test of RADA starts with processing and storing the data. Then all of the parameters of the model are loaded in the MATLAB Workspace. Next, the Simulink file used for the simulation is opened and the length of the simulation is set to match the length of the actual test. The simulation is run and the simulation output is stored. Finally, the data should be plotted and compared. === Using the MATLAB Data Parsing Tool === In-depth discussion of how to use the log file parsing tool is described [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] It is suggested to use the version of the tool in the rada_resarch_project git repository Paul Uhing used for his Master's research. It can be found on CO3050-11 under the ucart account in the directory ''~/rada_research_project/DataAnalysiTool_omnicoor/Tool''. Simply open MATLAB and set the working directory to this file path. In the MATLAB Command Prompt run ''DataAnalysis''. A popup window should open up. Select the log file you want to process and wait for the tool to finish processing the file. Once this is complete there should be four structures in the MATLAB workspace. -'''main''' : This contains all of the data extracted from the log file and the processing parameters used. main.expData contains two time structures: Time is used for the pendulum data and Eris_time is used for the ground vehicle data. -'''X_ref''' : This contains the reference vector in m/s for x velocity that is fed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Y_ref''' : This contains the reference vector in m/s for y velocity that is fed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Yaw_ref''' : This contains the reference vector in radians for yaw that is fed into Simulink. This expedites the simulation setup process, this used to be done by hand. This one is new in case people start testing the system with heading changes but is not used in the current setup. The first thing you should do is rename the main structure to the name you used for the log file. This is helpful for comparing multiple tests. Next, you will want to create two new variable ''Vquad_test'' and ''Vw_test''. In the MATLAB Command Prompt set the measured propeller voltage from the log file to ''Vquad_test'' and set the measured wheel voltage to ''Vw_test'' as this will be used by the simulation. Finally, if you did an open-loop test of the wheels create the variable ''Uol'' and set it to the open-loop wheel command used. Save all of these variables from the MATLAB workspace to a ''.mat'' file of the same name as the log file you extracted the data from and save it in the same directory as your RADA Simulink files. As of August 2nd, 2016 this directory is ''~/rada_research_project/MATLAB/RADA.'' === Setting up the MATLAB Workspace for Simulation === Change your MATLAB directory to this directory. Then run the simulation setup files. Currently, you only need to run ''modelParams_smallWheels_RADA'' in the MATLAB Command Prompt. Next, open the Simulink file that contains the model of RADA controlled by the controller you tested. -'''RADA_psiCtrl_v2_lqi_est.slx''' contains LQI, LQI+estimation, and LQG controller simulations. -'''RADA_psiCtrl_v2.slx''' contains the PID controlled system. -'''RADA_psiCtrl_v2_LQGsep.slx''' contains the subsystem LQG controlled system. -'''RADA_psiCtrl_v2_LQGsep_ol.slx''' contains the simulation of the pendulum system controlled by an LQG and Eris controlled with open-loop commands. Note all of the current (August 2nd, 2016) ''.slx'' files were created in MATLAB 2014b and will only work in MATLAB 2014b or newer. Then in the MATLAB Command Prompt type ''X_ref.time(end)'' exactly, don't add a semicolon, and hit enter. MATLAB will print the time of the last command in the X_ref structure. Set the end time of the simulation to this value and save your Simulink file. === Running Simulations and Storing Results === Before running the simulation make sure that the simulation is using the ''ode23t'' differential equations solver. This system is a moderately stiff system of differential and the ''ode45'' solver doesn't do well with these types of systems. When using ''ode23t'' is should only take a few minutes to run a 100+ second simulation while doing the same test using ''ode45'' could take 8 hours. While this is slow, it is also bad for your hard drive, as the simulation has to page between RAM and your computer's hard drive a lot. Once this check is done, run the simulation. While it is running, check what the output structures variables are named for your RADA test system. Once the simulation is done, go to your MATLAB Workspace and select all 15 outputs for your simulation or your sub-simulation if you used '''RADA_psiCtrl_v2_lqi_est.slx'''. Save these 15 output structures to a ''.mat'' file named as the log file with _sim appended to the end of the name. The 15 outputs are structures containing a time vector and then the data from the simulation sampled at 100 Hz and the units of this data are the SI units (ex: radians, m/s). There is one output structure for x velocity, y velocity, x body velocity, y body velocity, theta (pitch), phi (roll), psi (yaw), and one per actuator command (ex: the command sent to a wheel). Now you have all the data you can plot it. === Plotting Results === If you look at the ''DataSets'' folder below ''~/rada_research_project/MATLAB/RADA'' directory there are plenty of examples of how Paul Uhing compared simulation to test data. Generally, you should create an ''.m'' file with the same name as the log file this data was extracted from with _plot appended to the name. Generally you can just copy and paste for ''RADA_LQG_compPID_plot.m'', ''RADA_PID_compLQG_plot.m'', ''RADA_LQG_sep_plot.m'', or ''RADA_LQG_sep_ol_plot.m'' files and rename the structures for your test. These files create four figures. Figure 1 plots and compares the x velocity data in the first sub-figure and compares pitch (theta) data in the second sub-figure. Figure 2 does the same thing as Figure 1 but with y velocity and roll data. Figure 3 looks at the yaw data. Figure 4 looks at the sample period between UAV and ERIS packets from the camera system to check for periods of time with large packet drops. You can follow a similar pattern to compare motor commands. Make sure that you compare Quad Motor 2 from the test data with Quad Motor 4 from simulation and vice versa because propellers 2 and 4 were switched in Eris's software compared to the Model. That is all you need to know for testing RADA against the model. 31fb76a716619ebca86fd1ba5cf623071c57c9d0 345 344 2016-09-26T18:45:49Z Pfuhing 5 /* Building Software */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. The initial setup and how to test the system can also be applied to demoing RADA. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging Batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supply because it is the only power supply that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} The YouTube video link above should explain how to use the charger. RADA currently uses three different Lithium polymer (Lipo) batteries: 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo for the propellers. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery voltage drops really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAh 4-cell generally charge in 10-20 minutes apiece while the 2600 mAh 2-cell generally take up to 70 minutes to charge fully. === Setting up the Camera System === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password (not posted here for security reasons, but any one who works in the lab should know it). Once logged in, look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should have the naming scheme ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by date modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in the main project screen arrange themselves like the camera system configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another popup window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They have the naming scheme ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackables are open, the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation, left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. The orientation of the system represented by pitch, roll, and yaw Euler Angles. The Euler Angles orientation is determined by the order the angles are solved for determine the result. Tracking Tools doesn't use the same angle calculation order as RADA uses to calculate the system orientation so unless the pendulum is held near vertical the orientation given is not correct. General speaking if the system is held so that at least 2/3 angles are near zero you can approximate the orientation seen by the system by swapping the yaw a pitch angles shown by the real time information tab. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need to check to make sure the system is zeroed. #Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't, the front is the side opposite the switches and the side with the trackable constellation on it. #Make sure that the motor with the red motor mount is also facing the wall with the white boards. #Make sure the quad system is aligned along Eris Axis by standing behind the system. If the system is aligned, you should be able to block the mounting bolts of the front propeller motor with the pole while facing the east wall. #While holding the pendulum approximately vertical, see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. #Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and within a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise, go to the next step. #You need to zero the pendulum. ##Align ERIS so it is near zero yaw first (eye ball it). ##Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directions and hold it there. ##With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation'' button ##Now your friend can set the pendulum down and you can zero ERIS the same way. #Save the new trackable orientation by going to ''File->Save Trackables...'' and save a file using the same naming conventions as the trackable file you opened earlier. Use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use (the password isn't put here for security reasons). First, ensure that the RADA software is setup correctly for the test you want to run. To do this, you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below are compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will control using a tracking H2 controller. This controller doesn't have propeller velocity states so the controller makes use of the propellers. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will control the system using a H2 controller that contains propeller velocity states. This also causes the system to "Dance" because the propellers are slower than the wheels so the H2 controller will not use the propellers. -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propellers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by an LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to accelerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packet drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA Senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have found that even on a good strt the ''[ok]'' messages will still print. === Turning on RADA === Turning on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the switches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you use EITHER the WIFI adapter OR hardwired Ethernet, because the VRPN may listen to the camera data broadcast over both connections which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in, you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection in a command prompt. This is not the one you compile the code from so that you can recompile for different setup without needing to close the connection. If you are using a WIFI connection, use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connection use the command ''ssh root@192.168.0.54''. If the connection goes though you should be prompted for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the First Test After Power Up === For the first test after powering on Eris, a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect to the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell script will setup the NFS, and load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject'' and runs the executable. Once the user exits the executable, the log file produced is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist, it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see a warning that when copying the log file Eris couldn't maintain the file permission settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This date stamp uses the date on Eris, which is currently in June of 2008 as of August 2nd, 2016. Before starting the test, it is best to have someone spotting the pendulum and holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once the spotter is ready, run the shell script by using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA. You will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after startup you don't need to run this script. See the Section about Running additional tests below.r [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally, you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode, you can use the following commands to enter the desired mode with a three-second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode - this will only really work when using PIDs to control the pendulum. -''b'' : Enter robot control mode - in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode - the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I composts of the Pitch/Roll PIDs and only the PIDs. -''m'' : Adds a marker to the Log file in case odd things happen somewhere. This just increments a counter, so if you use it, look for changes in the marker value. ==== Robot Control Mode ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box step mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use the same commands as Tuning Mode. === Running Additional Tests === Once you have run one test with Eris on, it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_start_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result, it is ready to test much quicker. Before starting the test, it is best to have someone spotting the pendulum and holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell script by using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and Retrieving Log Files === If you are only demoing the system, there is no need to go beyond this point. Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files have the naming scheme ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful for describing what the test was conducted for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring Battery Voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there aren't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log are the header. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value later. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== #After test disconnect wheel battery from the system. #Measure voltage of battery using multimeter. [[Image:MeasureVwheel.jpg|800px]] You can use the plug used for charging the 2-cell Lipos but make sure to connect the plug to the multimeter before connecting the battery and disconnect the battery before disconnecting the plug from the mulitmeter. It is generally the best practice to give the multimeter a few minutes to allow for the voltage measurement to stabilize as the battery measurement tends to be a little low right after the test. The multimeter will report data out to four decimal places it is best just to round to three decimal places for the wheel voltage. ==== Propeller Battery ==== #Setup code to run all four propellers at 50% throttle, uncomment the definition of ''mot50'' in main.cpp and compile the project. #Power off propellers by turning off the switch to the ESCs. #Connect multimeter to measure the voltage across one of the ESCs. This is done by using the power splitter cord. ##Connect one of the female XT60 connectors on the splitter to a male XT60 connector to banana connector cable. ##The banana connector connects to the hand held multimeter. The multimeter should be set to the 20VDC measurement setting. ##Next unplug one the ESCs' power connection. ##Reconnect the ESC to power through the two remain connectors on the splitter cable. #Power on the propellers. #Run the system at 50% throttle and measure the steady-state voltage during the test. The battery will slow the voltage decay significantly, meaning it will keep the same measurement for a few seconds. #Stop the test and record the voltage in the log file. Make sure to disconnect the battery before removing the splitter cable. {| class="wikitable" style="text-align:center" |- | [[Image:PowerSplitter.jpg|200px]] | [[Image:QuadMultiCon.jpg |200px]] | [[Image:QuadMultiSet.JPG |200px]] | [[Image:QuadMeasESCcon.JPG|200px]] |- | Splitter cord. | Connect splitter to multimeter. | Settings for multimeter. | Connecting ESC through splitter. |} The testing setup should look like the image below: [[Image:QuadBattMeas.jpg|800px]] == Post Processing and Simulation == Simulating a test of RADA starts with processing and storing the data. Then all of the parameters of the model are loaded in the MATLAB Workspace. Next, the Simulink file used for the simulation is opened and the length of the simulation is set to match the length of the actual test. The simulation is run and the simulation output is stored. Finally, the data should be plotted and compared. === Using the MATLAB Data Parsing Tool === In-depth discussion of how to use the log file parsing tool is described [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] It is suggested to use the version of the tool in the rada_resarch_project git repository Paul Uhing used for his Master's research. It can be found on CO3050-11 under the ucart account in the directory ''~/rada_research_project/DataAnalysiTool_omnicoor/Tool''. Simply open MATLAB and set the working directory to this file path. In the MATLAB Command Prompt run ''DataAnalysis''. A popup window should open up. Select the log file you want to process and wait for the tool to finish processing the file. Once this is complete there should be four structures in the MATLAB workspace. -'''main''' : This contains all of the data extracted from the log file and the processing parameters used. main.expData contains two time structures: Time is used for the pendulum data and Eris_time is used for the ground vehicle data. -'''X_ref''' : This contains the reference vector in m/s for x velocity that is fed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Y_ref''' : This contains the reference vector in m/s for y velocity that is fed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Yaw_ref''' : This contains the reference vector in radians for yaw that is fed into Simulink. This expedites the simulation setup process, this used to be done by hand. This one is new in case people start testing the system with heading changes but is not used in the current setup. The first thing you should do is rename the main structure to the name you used for the log file. This is helpful for comparing multiple tests. Next, you will want to create two new variable ''Vquad_test'' and ''Vw_test''. In the MATLAB Command Prompt set the measured propeller voltage from the log file to ''Vquad_test'' and set the measured wheel voltage to ''Vw_test'' as this will be used by the simulation. Finally, if you did an open-loop test of the wheels create the variable ''Uol'' and set it to the open-loop wheel command used. Save all of these variables from the MATLAB workspace to a ''.mat'' file of the same name as the log file you extracted the data from and save it in the same directory as your RADA Simulink files. As of August 2nd, 2016 this directory is ''~/rada_research_project/MATLAB/RADA.'' === Setting up the MATLAB Workspace for Simulation === Change your MATLAB directory to this directory. Then run the simulation setup files. Currently, you only need to run ''modelParams_smallWheels_RADA'' in the MATLAB Command Prompt. Next, open the Simulink file that contains the model of RADA controlled by the controller you tested. -'''RADA_psiCtrl_v2_lqi_est.slx''' contains LQI, LQI+estimation, and LQG controller simulations. -'''RADA_psiCtrl_v2.slx''' contains the PID controlled system. -'''RADA_psiCtrl_v2_LQGsep.slx''' contains the subsystem LQG controlled system. -'''RADA_psiCtrl_v2_LQGsep_ol.slx''' contains the simulation of the pendulum system controlled by an LQG and Eris controlled with open-loop commands. Note all of the current (August 2nd, 2016) ''.slx'' files were created in MATLAB 2014b and will only work in MATLAB 2014b or newer. Then in the MATLAB Command Prompt type ''X_ref.time(end)'' exactly, don't add a semicolon, and hit enter. MATLAB will print the time of the last command in the X_ref structure. Set the end time of the simulation to this value and save your Simulink file. === Running Simulations and Storing Results === Before running the simulation make sure that the simulation is using the ''ode23t'' differential equations solver. This system is a moderately stiff system of differential and the ''ode45'' solver doesn't do well with these types of systems. When using ''ode23t'' is should only take a few minutes to run a 100+ second simulation while doing the same test using ''ode45'' could take 8 hours. While this is slow, it is also bad for your hard drive, as the simulation has to page between RAM and your computer's hard drive a lot. Once this check is done, run the simulation. While it is running, check what the output structures variables are named for your RADA test system. Once the simulation is done, go to your MATLAB Workspace and select all 15 outputs for your simulation or your sub-simulation if you used '''RADA_psiCtrl_v2_lqi_est.slx'''. Save these 15 output structures to a ''.mat'' file named as the log file with _sim appended to the end of the name. The 15 outputs are structures containing a time vector and then the data from the simulation sampled at 100 Hz and the units of this data are the SI units (ex: radians, m/s). There is one output structure for x velocity, y velocity, x body velocity, y body velocity, theta (pitch), phi (roll), psi (yaw), and one per actuator command (ex: the command sent to a wheel). Now you have all the data you can plot it. === Plotting Results === If you look at the ''DataSets'' folder below ''~/rada_research_project/MATLAB/RADA'' directory there are plenty of examples of how Paul Uhing compared simulation to test data. Generally, you should create an ''.m'' file with the same name as the log file this data was extracted from with _plot appended to the name. Generally you can just copy and paste for ''RADA_LQG_compPID_plot.m'', ''RADA_PID_compLQG_plot.m'', ''RADA_LQG_sep_plot.m'', or ''RADA_LQG_sep_ol_plot.m'' files and rename the structures for your test. These files create four figures. Figure 1 plots and compares the x velocity data in the first sub-figure and compares pitch (theta) data in the second sub-figure. Figure 2 does the same thing as Figure 1 but with y velocity and roll data. Figure 3 looks at the yaw data. Figure 4 looks at the sample period between UAV and ERIS packets from the camera system to check for periods of time with large packet drops. You can follow a similar pattern to compare motor commands. Make sure that you compare Quad Motor 2 from the test data with Quad Motor 4 from simulation and vice versa because propellers 2 and 4 were switched in Eris's software compared to the Model. That is all you need to know for testing RADA against the model. c15b0f0e0c89254006ea5042e57cf3c5aca94a37 346 345 2016-09-26T18:53:54Z Pfuhing 5 /* Testing Modes */ wikitext text/x-wiki This page will take you though setting up and testing RADA, retrieving the log file and other necessary data to run a simulation of that test and processing the data in MATLAB. Then actually running the simulation of RADA in Simulink. The initial setup and how to test the system can also be applied to demoing RADA. == Setting Up a RADA Test == Testing RADA is not overly difficult once you get the hang of the steps to setup RADA. The following steps may seem like a long process to go from starting the testing process to having completed simulation and plotting of the test results but this whole test procedure (with the exception of battery charging) can be completed in about 15-20 minutes. These steps are meant to be as detailed as possible in order to help new users of RADA get up and running as quickly as possible. '''<span style="color:red">NOTE: Always run RADA with at least 2 people!</span>''' The pendulum arm can crash into the ground if the network starts to drop packets and one person cannot give commands to RADA and spot the pendulum. This is a safety issue for both you and the RADA platform. === Charging Batteries === The lab currently uses mostly Hyperion batteries. We charge our batteries with a Hyperion EOS 1420i Net3 battery charger. For some general information about how to use this charger see [https://www.youtube.com/watch?v=-ox3EpzvsJ8 this video.]. In the lab we power this charger using the old Kepco Power supply because it is the only power supply that can supply enough current. Make sure that the power supply is set to an output voltage between 10.5V-29V. {| class="wikitable" style="text-align:center" |- | [[Image:ChargerPowerSupplyOff.JPG|400px]] | [[Image:ChargerPowerSuplyOn.JPG|400px]] |- | Kepco Power Supply off. | Kepco Power Supply on with correct voltage supply range. |} The YouTube video link above should explain how to use the charger. RADA currently uses three different Lithium polymer (Lipo) batteries: 1600 mAh 2-cell Lipo for the wheels, 2600 mAh 2-cell Lipo for the electronics of Eris, and a 2600 mAh 4-cell Lipo for the propellers. The 1600 mAh 2-cell Lipo can be charged using memory slot 2 of the charger. The 2600 mAh 2-cell Lipos can be charged using memory slot 3 for fast charging and memory slot 4 for slower charging (use this if the battery voltage drops really low for 10-20 minutes then switch to fast charging). The 2600 mAh 4-cell Lipo can be charged using memory slot 8. The 1600 mAh 2-cell and 2600 mAh 4-cell generally charge in 10-20 minutes apiece while the 2600 mAh 2-cell generally take up to 70 minutes to charge fully. === Setting up the Camera System === The camera system is run on the windows computer CO3050-07. You can log into this computer using a local microcart username and password (not posted here for security reasons, but any one who works in the lab should know it). Once logged in, look for Tracking Tools in the start menu or look for the shortcut shown below: [[Image:TrackingTools_shortcut.PNG|thumb|center|Tracking Tools shortcut]] Once the program opens the screen should look something like this: [[Image:NewTrackingTools.PNG|800px]] In the Tracking Tools Quick Start pop up menu select Open Existing Project and then navigate to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recent Tracking Tools project. It should have the naming scheme ''TrackingToolsProject YYYY-MM-DD timeStamp.ttp''. This is normally the most recently edited file when sorting by date modified. The most recent one as of August 1st, 2016 is ''TrackingToolsProject 2015-09-23 2.30pm.ttp''. [[Image:OpeningProject.PNG|800px]] You should notice that the cameras shown in the main project screen arrange themselves like the camera system configuration once the project has been opened. Now the constellations need to be loaded. This can be done by going to ''File->Open'' and another popup window will open. Navigate back to ''D:\Optitrack_Configuration'' (It should open to this directory by default) and select the most recently dated set of RADA trackables. They have the naming scheme ''RADA_entireSystem_M_D_YYYY.tra''. The most recent one as of August 1st, 2016 is ''RADA_entireSystem_7_8_2016.tra''. [[Image:Opening_trackables.PNG|800px]] Once the project and trackables are open, the cameras should appear in their constellation (square) and there should be two constellations under ''Project Explorer->Trackables''. One named UAV for the pendulum and one named ERIS for the ground vehicle. In order to get additional information about each constellation, left click on the the name of the desired trackable. [[Image:SelectingUAV.PNG|800px]] Once a trackable is selected more information about it is available in the ''Trackables'' Tab on the right side of the screen. For the current position and orientation look at the ''Real-Time Info'' sub-tab. The orientation of the system represented by pitch, roll, and yaw Euler Angles. The Euler Angles orientation is determined by the order the angles are solved for determine the result. Tracking Tools doesn't use the same angle calculation order as RADA uses to calculate the system orientation so unless the pendulum is held near vertical the orientation given is not correct. General speaking if the system is held so that at least 2/3 angles are near zero you can approximate the orientation seen by the system by swapping the yaw a pitch angles shown by the real time information tab. [[Image:Uav_realTimeInfo.PNG|800px]] Now we need to check to make sure the system is zeroed. #Hold RADA so that the front of the ground robot (ERIS is facing the wall with the white boards (east)). The front side of Eris is labeled. If it isn't, the front is the side opposite the switches and the side with the trackable constellation on it. #Make sure that the motor with the red motor mount is also facing the wall with the white boards. #Make sure the quad system is aligned along Eris Axis by standing behind the system. If the system is aligned, you should be able to block the mounting bolts of the front propeller motor with the pole while facing the east wall. #While holding the pendulum approximately vertical, see if the camera system reads zeros for the pendulum (UAV) pitch and roll (yaw and roll in ''Real-Time Info''). If yaw is off by a few degrees that is fine. #Compare the yaw of the UAV to that of ERIS (Remember this is pitch in ''Real-Time Info''). If they are both near zero and within a few degrees and the pendulum's pitch/roll were also near zero then you are ready to use the camera system. Otherwise, go to the next step. #You need to zero the pendulum. ##Align ERIS so it is near zero yaw first (eye ball it). ##Get a level and a friend. Have your friend use a level to ensure that the pendulum is level in both directions and hold it there. ##With the UAV constellation selected go to the ''Orientation'' tab (next to ''Real-Time Info'' tab) and click on ''Reset To Current Orientation'' button ##Now your friend can set the pendulum down and you can zero ERIS the same way. #Save the new trackable orientation by going to ''File->Save Trackables...'' and save a file using the same naming conventions as the trackable file you opened earlier. Use the current data so you don't have to re-zero the system the next time you test. [[Image:Uav_ResetOrientation.PNG|800px]] === Building Software === The development environment for running RADA is hosted on CO3050-11, a Linux Red Hat environment. This computer has a local ucart user name that you should use (the password isn't put here for security reasons). First, ensure that the RADA software is setup correctly for the test you want to run. To do this, you will need to open the main.cpp and logger.cpp files and make sure all of the compile time macros you want are defined correctly. All of the c++ files you should need to edit are in the directory ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss/src/Korebot'' Below are compiler macro options for main.cpp: -'''H2ctrl''' : This will cause the system to enter H2 controller mode where the whole RADA system is controlled by an H2 controller. -'''ssTracking''' : H2ctrl must also be defined for this macro to do anything. This macro will control using a tracking H2 controller. This controller doesn't have propeller velocity states so the controller makes use of the propellers. -'''ssMotors''' : H2ctrl must also be defined for this macro to do anything. This macro will control the system using a H2 controller that contains propeller velocity states. This also causes the system to "Dance" because the propellers are slower than the wheels so the H2 controller will not use the propellers. -'''ssDrop''' : Cause the system to go into packet drop controller mode. This mode allows controllers designed for lossy networks to be tested. Based off of other definitions how lossy the network is can be simulated. If nothing else is defined this controller becomes basically a H2 controller. -'''drop10''' : Will put the packet drop mode into 10% loss mode and use a controller designed for 10% loss. -'''drop30''' : Will put the packet drop mode into 30% loss mode and use a controller designed for 30% loss. -'''drop50''' : Will put the packet drop mode into 50% loss mode and use a controller designed for 50% loss. -'''mot50''' : This macro over-rides all other macros. If this is turned on the wheels will not run and the propellers will be run at 50% command. This is used for measuring the effective battery voltage seen by the ESCs. This is always run after a test. -'''RADAlqi''' : This macro will cause the system to use an LQI controller on the whole system. The linear velocity states are calculated with no filter and the angular velocity states are calculated with filters. -'''RADAlqi_est''' : This macro will cause the system to use an LQI controller on the whole system. A traditional estimator is used to estimate the states. -'''rada_lqg''' : This macro will cause the entire system to be controlled by an LQG controller/estimator system. -'''rada_split_lqg''' : This macro will cause the pendulum and ground robot to be controlled by their own LQG systems. -'''rada_split_lqg_ol''' : This macro will cause the pendulum to be controlled by an LQG controller, the yaw of the ground robot to be controlled by a PID controller, and the ground robot linear velocities to be controlled with open-loop commands. -'''yaw_off''' : This macro will cause the yaw control to be disabled on some controllers. *'''accR''' : This macro will cause the PID linear velocity controllers to be given ramps to accelerate from one velocity to another instead of steps. -'''posRamp''' : This macro will cause the linear velocities of RADA to be controlled by position PIDs with ramp reference instead of velocity commands. -If no controller selection is made all controllers revert to PID controllers All of these macros can be defined simply by uncommenting the corresponding define statement in main.cpp. The macros in the logger.cpp can be seen below: -'''ssDrop''' : This macro puts the logger into packet drop controller mode and logs the correct values for the packet drop controllers. -'''RADAlqi''' : This macro puts the logger into full system LQI controller logging mode. -'''RADAlqi_est''' : This macro puts the logger into full system LQI controller plus estimator logging mode. -'''rada_lqg''' : This puts the logger into full system LQG controller logging mode. -'''rada_split_lqg''' : This macro causes the logger to log data about the subsystem LQG controllers. -'''rada_split_lqg_ol''' : This cause the system to log data about the pendulum LQG system and the open-loop linear velocity commands. -'''H2ctrl''' : This macro causes the logger to log data about the full system H2 controllers. -If no logging mode is selected then the logger will default to logging PID data. Because the system only calculates controllers for one set of controllers it is important to ensure that the logger is in the correct mode based off of what is defined in main.cpp. As of August 1st, 2016 the defines in main.cpp are not seen in logger.cpp. Finally in a command prompt navigate to the driectroy: ''~/Desktop/rada_research_project/ErisResearchCode/CppProjects/MainProgram_PacketLoss'' Here just type: ''make''. The code will compile for your desired mode. For setting up a new development directory see [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Setting_up_a_new_development_environment Setting up a new development environment] from the RADA Senior Design wiki. [[Image:ComplingRADACode.png|800px]] The complied executable code ends up in ''/home/shared/MainProject''. The ''/home/shared'' directory is setup as a network file share (NFS). [[Image:ErisCompliedCode-config.png|800px]] This service needs to be restarted when CO3050-11 is restarted. [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Configuring_NFS_shares_for_the_robot Configure NFS shares for the robot] from the RADA Senior Design wiki. Be sure to use the new Linux install command in step six. Though I have found that even on a good strt the ''[ok]'' messages will still print. === Turning on RADA === Turning on Eris is fairly simple. Each system has its own battery. There is one for the wheels that plugs in at the front of Eris (opposite side of the switches), one for the electronics in the back of Eris (in between the switches), and one for the propellers that goes on top of Eris. [[Image:ErisOnPhoto.jpg|800px]] The wheel battery is normally 1600 mAh 2-cell Lipo but any 2-cell Lipo will work. The wheels are turned on by flipping the silver switch so the top points away from the system. The electronics normally use a 2600 mAh 2-cell Lipo. The electronics are turned on by flipping the green switch away from the system. It is important that you use EITHER the WIFI adapter OR hardwired Ethernet, because the VRPN may listen to the camera data broadcast over both connections which could cause problems. The propeller system is powered via a 2600 mAh 4-cell Lipo that connects to a power cable at the base of the pendulum. There is a switch to turn on the power to the propellers system. You will know it is on when the 1 on the switch is flush with the switch housing instead of sticking out. It takes about 30 seconds to a minute for Eris to boot up and start the networking connections. When the WIFI is plugged in, you will know it is ready when a blue light turns on, on the module. === Connecting to RADA === RADA is controlled through an SSH connection in a command prompt. This is not the one you compile the code from so that you can recompile for different setup without needing to close the connection. If you are using a WIFI connection, use the command ''ssh root@192.168.0.53''. If you are connected to Eris through a LAN connection use the command ''ssh root@192.168.0.54''. If the connection goes though you should be prompted for a password. The password is ''rootme''. [[Image:Ssh2Eris.png|800px]] It is important to close the SSH connection before turning off Eris because the terminal you are using will hang up if you don't. You can close the connection by using the command ''exit''. [[Image:ClosingSSH.png|800px]] == Testing RADA == Now that you are connected to Eris you can run tests. The testing is started by a few different methods. === Running the First Test After Power Up === For the first test after powering on Eris, a few additional steps need to be completed in order to test the system. The FPGA motor controller needs to be programmed and Eris needs to connect to the NFS server running on CO3050-11. This is accomplished by running ''1_co3050-11.sh'', this shell script will setup the NFS, and load the bit file into the FPGA configuration memory. Then it retrieves the executable file from the NFS server ''/mnt/nfs/MainProject'' and runs the executable. Once the user exits the executable, the log file produced is copied from the ''~/Logs/YYYY_MM_DD_Day'' directory on Eris to ''/home/shared/MainProject/Logs/YYYY_MM_DD_Day'' on CO3050-11. When the folder for the current Eris date doesn't exist, it creates this directory in CO3050-11 and then removes the directory and log file from Eris. You may see a warning that when copying the log file Eris couldn't maintain the file permission settings. This is normal as Eris doesn't have the same access to the NSF server as it has to its own files. This date stamp uses the date on Eris, which is currently in June of 2008 as of August 2nd, 2016. Before starting the test, it is best to have someone spotting the pendulum and holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once the spotter is ready, run the shell script by using the command ''./1_co3050-11.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. When you run this script there will be a bunch of information printed out about the PIC bus and loading the bit file to configure the FPGA. You will know that RADA is ready for the test when it asks you to select a running mode. See the Testing Modes section below. This script can take a while to complete so beyond the first test after startup you don't need to run this script. See the Section about Running additional tests below.r [[Image:StartingRADA initial.png|800px]] === Testing Modes === The RADA system has three testing modes: Robot Control Mode, Tuning Mode, and Box Step Mode. Additionally, you can exit the execution at any time by pressing the ''Esc'' key. Once the terminal asks you to chose a mode, you can use the following commands to enter the desired mode with a three-second delay or exit the program. You can also use these commands to switch between the modes. -''v'' : Enters the pendulum PID tuning mode - this will only really work when using PIDs to control the pendulum. -''b'' : Enter robot control mode - in this mode you can drive the robot around and the pendulum will try to stay vertical. This is the main mode used for testing the whole RADA system. -''n'' : Enters box step mode - the pendulum will change its desired pitch and roll angles every 20 seconds and move in a box shape. -''Esc'' : By hitting the escape key the program will exit the program. You will almost always want to run Robot Control Mode as the other modes are legacy modes from when we initially built and tested RADA and only works with the pendulum PID controllers. There are also a few utility commands that can be used in all modes. -''2'' : Resets I components of the Pitch/Roll PIDs and only the PIDs. IE: quad.pitch.PID_icomp=0 and quad.roll.PID_icomp=0; -''m'' : Adds a marker to the Log file. This can be done if there is a problem or if you are starting a new test. This way you can find these times in the log file. ==== Robot Control Mode ==== In Robot control mode you can control the motion of Eris. For PID control of Eris or 1D state feedback system the directional commands command Eris body velocity were for full system and Eris system state feedback controllers control the global velocity. All of these keys only need to be pressed not held down. -''w'' : Moves Eris forward (+x) at some velocity depending on the controller. -''s'' : Moves Eris in reverse (-x) at some velocity depending on the controller. -''d'' : Moves Eris in right (+y) at some velocity depending on the controller. -''a'' : Moves Eris in left (-y) at some velocity depending on the controller. -''p'' : Stops the motion of Eris (Set all velocity set points to zero). I.e. if you hit ''w'' then hit ''s'' then Eris will be moving in reverse. -''y'' : Moves Eris forward and to the right (+x/+y) simultaneously at some velocity depending on the controller. -''t'' : Moves Eris forward and to the left (+x/-y) simultaneously at some velocity depending on the controller. -''i'' : Moves Eris reverse and to the right (-x/+y) simultaneously at some velocity depending on the controller. -''y'' : Moves Eris reverse and to the left (-x/-y) simultaneously at some velocity depending on the controller. -''e'' : Rotate Eris clockwise (+yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''q'' : Rotate Eris counter-clockwise (-yaw) at some angular rate. This only worked when RADA used the closed-loop FPGA control of the wheels. There is currently no controllers that use this command. -''<'' : Increment Eris' desired heading 45 degrees counter-clockwise (-yaw). -''>'' : Increment Eris' desired heading 45 degrees clockwise (+yaw). -''7'' : Increments the pitch set point (+pitch). -''4'' : Decrements the pitch set point (-pitch). -''8'' : Increments the roll set point (+roll). -''5'' : Decrements the roll set point (-roll). ==== Tuning Mode ==== Tuning mode allows you to tune the PID controllers for both pitch and roll. The UI commands here are also available in Box Step Mode. -''1'' : Tune the Pitch PID. -''3'' : Tune the Roll PID. -''7'' : Increase proportional gain of PID being tuned. -''4'' : Decrease proportional gain of PID being tuned. -''8'' : Increase integral gain of PID being tuned. -''5'' : Decrease integral gain of PID being tuned. -''9'' : Increase derivative gain of PID being tuned. -''6'' : Decrease derivative gain of PID being tuned. -''i'' : Increase set point of PID being tuned. -''k'' : Decrease set point of PID being tuned. -''o'' : Increase integral windup term of PID being tuned. (Not used) -''l'' : Decrease integral windup term of PID being tuned. (Not used) ==== Box Step Mode ==== Box step mode will automatically change the set points of the pendulum every 20 seconds. The case statement for this mode can be changed for 1D and 2D step modes. This mode allows the user to use the same commands as Tuning Mode. === Running Additional Tests === Once you have run one test with Eris on, it is unnecessary to configure the FPGA or connect to the NFS server again. This is what took much of the time in the initial setup. This is what the script ''3_start_eris.sh'' was developed for. It does everything that ''1_co3050-11.sh'' does but without reprogramming the FPGA or reconnecting to the NFS server. As a result, it is ready to test much quicker. Before starting the test, it is best to have someone spotting the pendulum and holding it near vertical so that the pendulum doesn't have issues when entering a control mode.'''<span style="color:red"> Always ensure the pendulum is spotted by a second person when testing so you don't hurt yourself, others in the lab, or the RADA system.</span>''' Once you spotter is ready run the shell script by using the command ''./3_start_eris.sh'' in the terminal with the open SSH connection to Eris from the home, ''/root'', directory of Eris. [[Image:StartingRADA2nd.png|800px]] === Locating and Retrieving Log Files === If you are only demoing the system, there is no need to go beyond this point. Once you are done with a test that you want to compare to the model you should retrieve the log file right away so you don't mix it up with other test. On CO3050-11 go to the dircetory ''/home/shared/MainProject/Logs'' using the file browser (you can do this in a terminal but it is easier from the file explorer). Once there, look for the folder that has been modified most recently as Eris date is normally out of sync with its date and time. Then look for the newest log file. Log files have the naming scheme ''log(hh.mm.ss).txt'' (ex. log(13.04.51).txt). This naming convention works well to ensure that no log file is over written but it isn't useful for describing what the test was conducted for. Copy this log to the Desktop or to a USB drive and rename it. A good method is to name the file something like ''RADA_ctrl_otherNote#.txt'', where Describes what system you tested (ex. RADA, RADA1D, PEN1D, PEN2D), what typ of controller was used, other notes and then a number if this is a repeat of another test. This is much more useful when looking back at these logs later on. Before transferring the log file for processing you should record the wheel and propeller battery voltages in the header of the log file. The log file format is both human readable and can be parsed by MATALB. It was designed by the first RADA Senior Design Team and more information about the log files can be found [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] See he section below on measuring battery voltage below in order to get the best measurements for simulation of RADA. === Measuring Battery Voltages === The last thing that you need to do before simulating an experiment of the RADA platform is record the battery voltages for both the wheels and propellers. The wheel battery can be measured unloaded as there aren't large line losses between the battery and the H-bridges. The propeller battery voltage needs to be measured under load because the power cord running up the pendulum has significant line losses at the currents the propellers draw when in use. The battery voltages can be recorded in the log file for the test. Open the log file for the test you just completed (Use KWrite for Linux machines or Notepad++ for Windows machines). The first few lines of the log are the header. It should look like this: #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage Follow the procedure for measuring the voltage of each battery and then record the voltage under the corresponding battery. Then save the log file and close out of your text editor and the test will be ready for processing. Recoding the battery voltages in this way makes it much easier to find if you need the value later. The final log file header should look like this once you are done #Constants pitch_P pitch_I pitch_D #PIDValues 48000 18000 21000 #Constants roll_P roll_I roll_D #PIDValues 48000 18000 21000 #Battery Vquad Vwheels #Voltage 14.44 8.257 ==== Wheel Battery ==== #After test disconnect wheel battery from the system. #Measure voltage of battery using multimeter. [[Image:MeasureVwheel.jpg|800px]] You can use the plug used for charging the 2-cell Lipos but make sure to connect the plug to the multimeter before connecting the battery and disconnect the battery before disconnecting the plug from the mulitmeter. It is generally the best practice to give the multimeter a few minutes to allow for the voltage measurement to stabilize as the battery measurement tends to be a little low right after the test. The multimeter will report data out to four decimal places it is best just to round to three decimal places for the wheel voltage. ==== Propeller Battery ==== #Setup code to run all four propellers at 50% throttle, uncomment the definition of ''mot50'' in main.cpp and compile the project. #Power off propellers by turning off the switch to the ESCs. #Connect multimeter to measure the voltage across one of the ESCs. This is done by using the power splitter cord. ##Connect one of the female XT60 connectors on the splitter to a male XT60 connector to banana connector cable. ##The banana connector connects to the hand held multimeter. The multimeter should be set to the 20VDC measurement setting. ##Next unplug one the ESCs' power connection. ##Reconnect the ESC to power through the two remain connectors on the splitter cable. #Power on the propellers. #Run the system at 50% throttle and measure the steady-state voltage during the test. The battery will slow the voltage decay significantly, meaning it will keep the same measurement for a few seconds. #Stop the test and record the voltage in the log file. Make sure to disconnect the battery before removing the splitter cable. {| class="wikitable" style="text-align:center" |- | [[Image:PowerSplitter.jpg|200px]] | [[Image:QuadMultiCon.jpg |200px]] | [[Image:QuadMultiSet.JPG |200px]] | [[Image:QuadMeasESCcon.JPG|200px]] |- | Splitter cord. | Connect splitter to multimeter. | Settings for multimeter. | Connecting ESC through splitter. |} The testing setup should look like the image below: [[Image:QuadBattMeas.jpg|800px]] == Post Processing and Simulation == Simulating a test of RADA starts with processing and storing the data. Then all of the parameters of the model are loaded in the MATLAB Workspace. Next, the Simulink file used for the simulation is opened and the length of the simulation is set to match the length of the actual test. The simulation is run and the simulation output is stored. Finally, the data should be plotted and compared. === Using the MATLAB Data Parsing Tool === In-depth discussion of how to use the log file parsing tool is described [http://wikis.ece.iastate.edu/robotic-agriculture-data-acquisition/index.php/Data_Analysis_Tool here.] It is suggested to use the version of the tool in the rada_resarch_project git repository Paul Uhing used for his Master's research. It can be found on CO3050-11 under the ucart account in the directory ''~/rada_research_project/DataAnalysiTool_omnicoor/Tool''. Simply open MATLAB and set the working directory to this file path. In the MATLAB Command Prompt run ''DataAnalysis''. A popup window should open up. Select the log file you want to process and wait for the tool to finish processing the file. Once this is complete there should be four structures in the MATLAB workspace. -'''main''' : This contains all of the data extracted from the log file and the processing parameters used. main.expData contains two time structures: Time is used for the pendulum data and Eris_time is used for the ground vehicle data. -'''X_ref''' : This contains the reference vector in m/s for x velocity that is fed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Y_ref''' : This contains the reference vector in m/s for y velocity that is fed into Simulink. This expedites the simulation setup process, this used to be done by hand. -'''Yaw_ref''' : This contains the reference vector in radians for yaw that is fed into Simulink. This expedites the simulation setup process, this used to be done by hand. This one is new in case people start testing the system with heading changes but is not used in the current setup. The first thing you should do is rename the main structure to the name you used for the log file. This is helpful for comparing multiple tests. Next, you will want to create two new variable ''Vquad_test'' and ''Vw_test''. In the MATLAB Command Prompt set the measured propeller voltage from the log file to ''Vquad_test'' and set the measured wheel voltage to ''Vw_test'' as this will be used by the simulation. Finally, if you did an open-loop test of the wheels create the variable ''Uol'' and set it to the open-loop wheel command used. Save all of these variables from the MATLAB workspace to a ''.mat'' file of the same name as the log file you extracted the data from and save it in the same directory as your RADA Simulink files. As of August 2nd, 2016 this directory is ''~/rada_research_project/MATLAB/RADA.'' === Setting up the MATLAB Workspace for Simulation === Change your MATLAB directory to this directory. Then run the simulation setup files. Currently, you only need to run ''modelParams_smallWheels_RADA'' in the MATLAB Command Prompt. Next, open the Simulink file that contains the model of RADA controlled by the controller you tested. -'''RADA_psiCtrl_v2_lqi_est.slx''' contains LQI, LQI+estimation, and LQG controller simulations. -'''RADA_psiCtrl_v2.slx''' contains the PID controlled system. -'''RADA_psiCtrl_v2_LQGsep.slx''' contains the subsystem LQG controlled system. -'''RADA_psiCtrl_v2_LQGsep_ol.slx''' contains the simulation of the pendulum system controlled by an LQG and Eris controlled with open-loop commands. Note all of the current (August 2nd, 2016) ''.slx'' files were created in MATLAB 2014b and will only work in MATLAB 2014b or newer. Then in the MATLAB Command Prompt type ''X_ref.time(end)'' exactly, don't add a semicolon, and hit enter. MATLAB will print the time of the last command in the X_ref structure. Set the end time of the simulation to this value and save your Simulink file. === Running Simulations and Storing Results === Before running the simulation make sure that the simulation is using the ''ode23t'' differential equations solver. This system is a moderately stiff system of differential and the ''ode45'' solver doesn't do well with these types of systems. When using ''ode23t'' is should only take a few minutes to run a 100+ second simulation while doing the same test using ''ode45'' could take 8 hours. While this is slow, it is also bad for your hard drive, as the simulation has to page between RAM and your computer's hard drive a lot. Once this check is done, run the simulation. While it is running, check what the output structures variables are named for your RADA test system. Once the simulation is done, go to your MATLAB Workspace and select all 15 outputs for your simulation or your sub-simulation if you used '''RADA_psiCtrl_v2_lqi_est.slx'''. Save these 15 output structures to a ''.mat'' file named as the log file with _sim appended to the end of the name. The 15 outputs are structures containing a time vector and then the data from the simulation sampled at 100 Hz and the units of this data are the SI units (ex: radians, m/s). There is one output structure for x velocity, y velocity, x body velocity, y body velocity, theta (pitch), phi (roll), psi (yaw), and one per actuator command (ex: the command sent to a wheel). Now you have all the data you can plot it. === Plotting Results === If you look at the ''DataSets'' folder below ''~/rada_research_project/MATLAB/RADA'' directory there are plenty of examples of how Paul Uhing compared simulation to test data. Generally, you should create an ''.m'' file with the same name as the log file this data was extracted from with _plot appended to the name. Generally you can just copy and paste for ''RADA_LQG_compPID_plot.m'', ''RADA_PID_compLQG_plot.m'', ''RADA_LQG_sep_plot.m'', or ''RADA_LQG_sep_ol_plot.m'' files and rename the structures for your test. These files create four figures. Figure 1 plots and compares the x velocity data in the first sub-figure and compares pitch (theta) data in the second sub-figure. Figure 2 does the same thing as Figure 1 but with y velocity and roll data. Figure 3 looks at the yaw data. Figure 4 looks at the sample period between UAV and ERIS packets from the camera system to check for periods of time with large packet drops. You can follow a similar pattern to compare motor commands. Make sure that you compare Quad Motor 2 from the test data with Quad Motor 4 from simulation and vice versa because propellers 2 and 4 were switched in Eris's software compared to the Model. That is all you need to know for testing RADA against the model. fe427fe26aec7589c4ea6b4e360e14a2f71da349 Controller 0 5 319 229 2016-08-28T21:32:02Z Jnoronha 3 /* Initialize the PID's */ changed to SYNTAXHIGHLIGHT for code examples wikitext text/x-wiki The Crazyflie platform is completely customizable when it comes to the control design. As long as the controller can be written in C or C++, we can implement it in the Platform. This applies to both the controllers run on the PC Client and the controllers run on the Firmware of the Crazyflie. Originally the only controllers in the Platform were Firmware PID's that controlled the angular position and rates of the Crazyflie for hand flight. The original controller layout can be seen here [[#Original PID Controllers (Angular Rotation)|Original PID's]]. Below you will find documentation on the different types of Controllers that have been applied to the platform, organized by their location in the Platform. == Firmware == === Original PID Controllers (Angular Rotation) === Directly on the Crazyflie Firmware there are 5 PID controllers as seen here: [[Image:FirmwareOnlyPIDArchitecture.png|500px]] The Pitch and Roll angular position PID's receive constant setpoints from some outside source (gamepad controller or automated controller). The outputs of those angular position controllers is then fed into the angular rate controllers as shown. This final output is then fed into the Motor Command block which converts the angular rate setpoints into motor commands. ---- ===State Estimator (Not Implemented Yet)=== ('''***NOT YET IMPLEMENTED***''') Bitcraze is currently working on adding a state estimator and state-feedback controller onto the Firmware to handle control calculations instead of the PID. The code is in place but the controller is not yet used as of '''7/13/16'''. == PC Client == === Client PID Controllers (Position and Yaw) === The first controller implemented on the Client were 4 PID controllers used to stabilize the Crazyflie's position in X, Y, and Z, and angular position in Yaw respectively. These PID's feed directly into the Firmware PID's as seen here: [[Image:CompletePIDArchitectureFigure.png|500px]] The controllers inside the red box are the original PID controllers located on the Firmware as shown above in the [[#Original PID Controllers (Angular Rotation)|Original PID's]]. ====Initialize the PID's==== :1. To start we create a struct with all the necessary variables (code from ''pid.h''): ::<syntaxhighlight lang="cpp"> typedef struct { float desired; //< set point float error; //< error float prevError; //< previous error float integ; //< integral float deriv; //< derivative float kp; //< proportional gain float ki; //< integral gain float kd; //< derivative gain float outP; //< proportional output (debugging) float outI; //< integral output (debugging) float outD; //< derivative output (debugging) float iLimit; //< integral limit float iLimitLow; //< integral limit float dt; //< delta-time dt float angularLimit; //sets limit for how far Crazyflie can tip, to prevent flipping float angularLimitLow; //^ float thrustLimit; //Sets upper limit for Thrust Output (60000?) **? float thrustLimitLow; //Sets lower limit for thrust Output (10001) } PidObject; </syntaxhighlight> :2. To simplify scaling up the code to multiple Crazyflies, we will create a <code> ControllerObject </code> that contains multiple PID structs as shown (code in ''controller.h''): ::<syntaxhighlight lang="cpp"> typedef struct { PidObject pidRoll; PidObject pidPitch; PidObject pidYaw; PidObject pidX; PidObject pidY; PidObject pidZ; bool isInit; } ControllerObject; </syntaxhighlight> :3. Then we initialize the Objects to 0 at the start of each run (code in ''eris_vrpn.cpp''): ::<syntaxhighlight lang="cpp"> ControllerObject pidCtrl1 = { 0 }; // init all fields to zero ControllerObject pidCtrl2 = { 0 }; // init all fields to zero ControllerObject pidCtrl3 = { 0 }; // init all fields to zero ControllerObject pidCtrl4 = { 0 }; // init all fields to zero </syntaxhighlight> :4. Then populate the PidObjects with the desired parameters (code in ''pid.c''): ::<syntaxhighlight lang="cpp"> void pidInit(PidObject* pid, const float desired, const float kp, const float ki, const float kd, const float dt) { pid->error = 0; pid->prevError = 0; pid->integ = 0; pid->deriv = 0; pid->desired = desired; pid->kp = kp; pid->ki = ki; pid->kd = kd; pid->iLimit = DEFAULT_PID_INTEGRATION_LIMIT; pid->iLimitLow = -DEFAULT_PID_INTEGRATION_LIMIT; pid->angularLimit = DEFAULT_PID_ANGLE_OUTPUT; pid->angularLimitLow = -DEFAULT_PID_ANGLE_OUTPUT; pid->thrustLimit = DEFAULT_PID_HIGH_THRUST_LIMIT; pid->thrustLimitLow = DEFAULT_PID_LOW_THRUST_LIMIT; pid->dt = dt; } </syntaxhighlight> Using the above function for each of the <code>PidObjects</code> inside of the <code>ControllerObject</code> below (code in ''controller.c''): ::<syntaxhighlight lang="cpp"> void controllerInit( ControllerObject * ctrl ) { if(ctrl->isInit) return; pidInit(&ctrl->pidY, 0, PID_Y_KP, PID_Y_KI, PID_Y_KD, CAMERA_UPDATE_DT); //for Roll PID pidInit(&ctrl->pidX, 0, PID_X_KP, PID_X_KI, PID_X_KD, CAMERA_UPDATE_DT); //for Pitch PID pidInit(&ctrl->pidYaw, 0, PID_YAW_KP, PID_YAW_KI, PID_YAW_KD, CAMERA_UPDATE_DT); pidInit(&ctrl->pidZ, 0, PID_Z_KP, PID_Z_KI, PID_Z_KD, CAMERA_UPDATE_DT); pidSetIntegralLimit(&ctrl->pidY, PID_Y_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidX, PID_X_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidYaw, PID_YAW_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidZ, PID_Z_INTEGRATION_LIMIT); ctrl->isInit = true; } </syntaxhighlight> '''Note:''' If we have multiple Crazyflies we need a <code>ControllerObject</code> for each Crazyflie (code in ''eris_vrpn.cpp'') ::<syntaxhighlight lang="cpp"> controllerResetAllPID( &pidCtrl1 ); controllerInit( &pidCtrl1 ); #endif #if NUM_QUADS >= 2 controllerResetAllPID( &pidCtrl2 ); controllerInit( &pidCtrl2 ); #endif #if NUM_QUADS >=3 controllerResetAllPID( &pidCtrl3 ); controllerInit( &pidCtrl3 ); #endif #if NUM_QUADS >=4 controllerResetAllPID( &pidCtrl4 ); controllerInit( &pidCtrl4 ); #endif </syntaxhighlight> Now the initialization of the Controllers is complete. ====Calculating the PID's==== :1. Each loop we want to calculate the PID output (code in ''pid.c''): <blockquote> <code> <pre> float pidUpdateAngle(PidObject* pid, const float measured, const bool updateError) //**USED FOR ATTITUDE CONTROL { float output; if(updateError) { pid->error = pid->desired - measured; //Calculates current error } pid->integ += pid->error * pid->dt; //Calculates integral term if(pid->integ > pid->iLimit) //Checks that the integral term stays below the integral limit (anti-windup) { pid->integ = pid->iLimit; } else if(pid->integ < pid->iLimitLow) { pid->integ = pid->iLimitLow; } pid->deriv = (pid->error - pid->prevError) / pid->dt; //Calculates derivative term pid->outP = pid->kp* pid->error; pid->outI = pid->ki * pid->integ; pid->outD = pid->kd * pid->deriv; output = pid->outP + pid->outI + pid->outD; //Adds up all 3 calculated terms for output if(output > pid->angularLimit) //Limits amount Crazyflie can tip { output = pid->angularLimit; } if(output < pid->angularLimitLow) //Limits amount Crazyflie can tip { output = pid->angularLimitLow; } pid->prevError = pid->error; //Stores the current error for next loop return output; } </pre> </code> </blockquote> ::'''Note:''' There are 3 different versions of this Function (for Angle, Thrust, and Yaw) since each has different output limits. :2. Using the function above, combine all PID calculations into one function (code in ''controller.c''): <blockquote> <code> <pre> void controllerCorrectAttitudePID(ControllerObject * ctrl, float xPositionActual, float yPositionActual, float zPositionActual, float eulerYawActual, float xPositionDesired, float yPositionDesired, float zPositionDesired, float eulerYawDesired, float* rollControlOutput, float* pitchControlOutput, float* yawControlOutput, float* thrustControlOutput) { pidSetDesired(&ctrl->pidX, xPositionDesired); *pitchControlOutput = pidUpdateAngle(&ctrl->pidX, xPositionActual, false); //Originally true pidSetDesired(&ctrl->pidY, yPositionDesired); *rollControlOutput = pidUpdateAngle(&ctrl->pidY, yPositionActual, false); //Originally true pidSetDesired(&ctrl->pidZ, zPositionDesired); *thrustControlOutput = pidUpdateThrust(&ctrl->pidZ,zPositionActual, true); float yawError; pidSetDesired(&ctrl->pidYaw, eulerYawDesired); yawError = eulerYawDesired - eulerYawActual; if(yawError > 180.0) //Ensures Yaw error stays between -180 and 180 degrees yawError -= 360.0; else if(yawError < -180.0) yawError += 360.0; pidSetError(&ctrl->pidYaw, yawError); *yawControlOutput = pidUpdateYaw(&ctrl->pidYaw, eulerYawActual, true); //originally false } </pre> </code> </blockquote> :3. In each Callback, calculate the Controller outputs, assigned to pointer values <code>*rollControlOutput</code>, <code>*pitchControlOutput</code>, etc... (code in ''eris_vrpn.cpp''): <blockquote> <code> <pre> xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; //Calculates error externally controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); </pre> </code> </blockquote> ::'''Note 1:''' We calculate error externally for X and Y because certain swarm controllers need special setpoint modifiers (this way we can switch modes without effecting the default setpoint): ::'''Note 2:''' Swap out the Controller - all we need to do is create a similar function and replace ''controllerCorrectAttitudePID'' above ::'''Example:''' Follow Hand Mode Error (Crazyflie1 will have setpoint -0.5 m lower in X and +0.5 m higher in Y than your hand trackable): <blockquote> <code> <pre> ... xError1 = (xPositionHand - 0.5) - xPosition1; yError1 = (yPositionHand + 0.5) - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); ... </pre> </code> </blockquote> :4. Send Calculated Control Outputs to the Crazyflie via the Radio (code found in ''simple.cpp''): <blockquote> <code> <pre> RunCrazyflie(crRadio2, cflieCopter3, rollControlOutput3, pitchControlOutput3, yawControlOutput3, thrustControlOutput3); </pre> </code> </blockquote> ::Where the ''RunCrazyflie'' function looks like this (code in ''simple.cpp''): <blockquote> <code> <pre> int RunCrazyflie(CCrazyRadio *crRadio, CCrazyflie *cflieCopter, float rollControl, float pitchControl, float yawControl, float thrustControl) { //Timing Index Variables (**FOR TESTING ROUTINES**) int i = 0; while(cflieCopter->cycle()) { //If Crazyflie is vertical kill motors, Crash Imminent if(cflieCopter->roll() > 90){ cflieCopter->setThrust(10000); } else if(cflieCopter->roll() < -90){ cflieCopter->setThrust(10000); } else if(cflieCopter->pitch() > 90){ cflieCopter->setThrust(10000); } else if(cflieCopter->pitch() < -90){ cflieCopter->setThrust(10000); } //Otherwise Send Setpoints else if(i < 1){ //i < 200000 cflieCopter->setThrust(thrustControl); cflieCopter->setRoll(rollControl); cflieCopter->setPitch(pitchControl); cflieCopter->setYaw(-yawControl); //******SET TO NEGATIVE FOR CAMERA SYSTEM YAW BEING REVERSED!!!!**** i++; } else{ break; } } return 0; } </pre> </code> </blockquote> ::'''IMPORTANT:''' This function contains the function <code>cflieCopter->cycle()</code> which is CRITICAL to maintaining communications with the Crazyflie. The ''cycle'' function initiates communications, sends setpoints, and must be called frequently otherwise the communications will timeout and the Crazyflie will stop as a precaution. :5. Repeat steps 3 through 5 for each set of new location data...until Program END. ===Swapping Client Controller Type=== With the Swarm Platform we can plug any controller (that can be coded in C or C++) into the Client to control the Crazyflies. In steps 1, 2, and 3 of the [[#Calculating the PID's|Calculating the PID's]] section, you can see the whole process of how we calculate the control output. To replace the PID with a different controller we can follow those steps but with our new controller. So as a general idea of the process we have: ('''Note:''' This depends heavily on how your controller works, this is generalized for a single input single output controller) #Implement the New Controller Output Calculation in C as a function #Create multiple instances of this controller calculation function (for each Degree of Freedom (DOF) you need to control) and combine them into a function to calculate all controllers with 1 function call ('''Note:''' This step is for ease of code use, NOT Required) #In each Callback, call the function to Calculate the Controller output. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> db1974ad37eeb69b593ee9a14976e4916c27a665 320 319 2016-08-28T21:38:21Z Jnoronha 3 changed to SYNTAX HIGHLIGHT wikitext text/x-wiki The Crazyflie platform is completely customizable when it comes to the control design. As long as the controller can be written in C or C++, we can implement it in the Platform. This applies to both the controllers run on the PC Client and the controllers run on the Firmware of the Crazyflie. Originally the only controllers in the Platform were Firmware PID's that controlled the angular position and rates of the Crazyflie for hand flight. The original controller layout can be seen here [[#Original PID Controllers (Angular Rotation)|Original PID's]]. Below you will find documentation on the different types of Controllers that have been applied to the platform, organized by their location in the Platform. == Firmware == === Original PID Controllers (Angular Rotation) === Directly on the Crazyflie Firmware there are 5 PID controllers as seen here: [[Image:FirmwareOnlyPIDArchitecture.png|500px]] The Pitch and Roll angular position PID's receive constant setpoints from some outside source (gamepad controller or automated controller). The outputs of those angular position controllers is then fed into the angular rate controllers as shown. This final output is then fed into the Motor Command block which converts the angular rate setpoints into motor commands. ---- ===State Estimator (Not Implemented Yet)=== ('''***NOT YET IMPLEMENTED***''') Bitcraze is currently working on adding a state estimator and state-feedback controller onto the Firmware to handle control calculations instead of the PID. The code is in place but the controller is not yet used as of '''7/13/16'''. == PC Client == === Client PID Controllers (Position and Yaw) === The first controller implemented on the Client were 4 PID controllers used to stabilize the Crazyflie's position in X, Y, and Z, and angular position in Yaw respectively. These PID's feed directly into the Firmware PID's as seen here: [[Image:CompletePIDArchitectureFigure.png|500px]] The controllers inside the red box are the original PID controllers located on the Firmware as shown above in the [[#Original PID Controllers (Angular Rotation)|Original PID's]]. ====Initialize the PID's==== :1. To start we create a struct with all the necessary variables (code from ''pid.h''): ::<syntaxhighlight lang="cpp"> typedef struct { float desired; //< set point float error; //< error float prevError; //< previous error float integ; //< integral float deriv; //< derivative float kp; //< proportional gain float ki; //< integral gain float kd; //< derivative gain float outP; //< proportional output (debugging) float outI; //< integral output (debugging) float outD; //< derivative output (debugging) float iLimit; //< integral limit float iLimitLow; //< integral limit float dt; //< delta-time dt float angularLimit; //sets limit for how far Crazyflie can tip, to prevent flipping float angularLimitLow; //^ float thrustLimit; //Sets upper limit for Thrust Output (60000?) **? float thrustLimitLow; //Sets lower limit for thrust Output (10001) } PidObject; </syntaxhighlight> :2. To simplify scaling up the code to multiple Crazyflies, we will create a <code> ControllerObject </code> that contains multiple PID structs as shown (code in ''controller.h''): ::<syntaxhighlight lang="cpp"> typedef struct { PidObject pidRoll; PidObject pidPitch; PidObject pidYaw; PidObject pidX; PidObject pidY; PidObject pidZ; bool isInit; } ControllerObject; </syntaxhighlight> :3. Then we initialize the Objects to 0 at the start of each run (code in ''eris_vrpn.cpp''): ::<syntaxhighlight lang="cpp"> ControllerObject pidCtrl1 = { 0 }; // init all fields to zero ControllerObject pidCtrl2 = { 0 }; // init all fields to zero ControllerObject pidCtrl3 = { 0 }; // init all fields to zero ControllerObject pidCtrl4 = { 0 }; // init all fields to zero </syntaxhighlight> :4. Then populate the PidObjects with the desired parameters (code in ''pid.c''): ::<syntaxhighlight lang="cpp"> void pidInit(PidObject* pid, const float desired, const float kp, const float ki, const float kd, const float dt) { pid->error = 0; pid->prevError = 0; pid->integ = 0; pid->deriv = 0; pid->desired = desired; pid->kp = kp; pid->ki = ki; pid->kd = kd; pid->iLimit = DEFAULT_PID_INTEGRATION_LIMIT; pid->iLimitLow = -DEFAULT_PID_INTEGRATION_LIMIT; pid->angularLimit = DEFAULT_PID_ANGLE_OUTPUT; pid->angularLimitLow = -DEFAULT_PID_ANGLE_OUTPUT; pid->thrustLimit = DEFAULT_PID_HIGH_THRUST_LIMIT; pid->thrustLimitLow = DEFAULT_PID_LOW_THRUST_LIMIT; pid->dt = dt; } </syntaxhighlight> Using the above function for each of the <code>PidObjects</code> inside of the <code>ControllerObject</code> below (code in ''controller.c''): ::<syntaxhighlight lang="cpp"> void controllerInit( ControllerObject * ctrl ) { if(ctrl->isInit) return; pidInit(&ctrl->pidY, 0, PID_Y_KP, PID_Y_KI, PID_Y_KD, CAMERA_UPDATE_DT); //for Roll PID pidInit(&ctrl->pidX, 0, PID_X_KP, PID_X_KI, PID_X_KD, CAMERA_UPDATE_DT); //for Pitch PID pidInit(&ctrl->pidYaw, 0, PID_YAW_KP, PID_YAW_KI, PID_YAW_KD, CAMERA_UPDATE_DT); pidInit(&ctrl->pidZ, 0, PID_Z_KP, PID_Z_KI, PID_Z_KD, CAMERA_UPDATE_DT); pidSetIntegralLimit(&ctrl->pidY, PID_Y_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidX, PID_X_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidYaw, PID_YAW_INTEGRATION_LIMIT); pidSetIntegralLimit(&ctrl->pidZ, PID_Z_INTEGRATION_LIMIT); ctrl->isInit = true; } </syntaxhighlight> '''Note:''' If we have multiple Crazyflies we need a <code>ControllerObject</code> for each Crazyflie (code in ''eris_vrpn.cpp'') ::<syntaxhighlight lang="cpp"> controllerResetAllPID( &pidCtrl1 ); controllerInit( &pidCtrl1 ); #endif #if NUM_QUADS >= 2 controllerResetAllPID( &pidCtrl2 ); controllerInit( &pidCtrl2 ); #endif #if NUM_QUADS >=3 controllerResetAllPID( &pidCtrl3 ); controllerInit( &pidCtrl3 ); #endif #if NUM_QUADS >=4 controllerResetAllPID( &pidCtrl4 ); controllerInit( &pidCtrl4 ); #endif </syntaxhighlight> Now the initialization of the Controllers is complete. ====Calculating the PID's==== :1. Each loop we want to calculate the PID output (code in ''pid.c''): ::<syntaxhighlight lang="cpp"> float pidUpdateAngle(PidObject* pid, const float measured, const bool updateError) //**USED FOR ATTITUDE CONTROL { float output; if(updateError) { pid->error = pid->desired - measured; //Calculates current error } pid->integ += pid->error * pid->dt; //Calculates integral term if(pid->integ > pid->iLimit) //Checks that the integral term stays below the integral limit (anti-windup) { pid->integ = pid->iLimit; } else if(pid->integ < pid->iLimitLow) { pid->integ = pid->iLimitLow; } pid->deriv = (pid->error - pid->prevError) / pid->dt; //Calculates derivative term pid->outP = pid->kp* pid->error; pid->outI = pid->ki * pid->integ; pid->outD = pid->kd * pid->deriv; output = pid->outP + pid->outI + pid->outD; //Adds up all 3 calculated terms for output if(output > pid->angularLimit) //Limits amount Crazyflie can tip { output = pid->angularLimit; } if(output < pid->angularLimitLow) //Limits amount Crazyflie can tip { output = pid->angularLimitLow; } pid->prevError = pid->error; //Stores the current error for next loop return output; } </syntaxhighlight> ::'''Note:''' There are 3 different versions of this Function (for Angle, Thrust, and Yaw) since each has different output limits. :2. Using the function above, combine all PID calculations into one function (code in ''controller.c''): ::<syntaxhighlight lang="cpp"> void controllerCorrectAttitudePID(ControllerObject * ctrl, float xPositionActual, float yPositionActual, float zPositionActual, float eulerYawActual, float xPositionDesired, float yPositionDesired, float zPositionDesired, float eulerYawDesired, float* rollControlOutput, float* pitchControlOutput, float* yawControlOutput, float* thrustControlOutput) { pidSetDesired(&ctrl->pidX, xPositionDesired); *pitchControlOutput = pidUpdateAngle(&ctrl->pidX, xPositionActual, false); //Originally true pidSetDesired(&ctrl->pidY, yPositionDesired); *rollControlOutput = pidUpdateAngle(&ctrl->pidY, yPositionActual, false); //Originally true pidSetDesired(&ctrl->pidZ, zPositionDesired); *thrustControlOutput = pidUpdateThrust(&ctrl->pidZ,zPositionActual, true); float yawError; pidSetDesired(&ctrl->pidYaw, eulerYawDesired); yawError = eulerYawDesired - eulerYawActual; if(yawError > 180.0) //Ensures Yaw error stays between -180 and 180 degrees yawError -= 360.0; else if(yawError < -180.0) yawError += 360.0; pidSetError(&ctrl->pidYaw, yawError); *yawControlOutput = pidUpdateYaw(&ctrl->pidYaw, eulerYawActual, true); //originally false } </syntaxhighlight> :3. In each Callback, calculate the Controller outputs, assigned to pointer values <code>*rollControlOutput</code>, <code>*pitchControlOutput</code>, etc... (code in ''eris_vrpn.cpp''): ::<syntaxhighlight lang="cpp"> xError1 = xPositionDesired1 - xPosition1; yError1 = yPositionDesired1 - yPosition1; //Calculates error externally controllerSetXYError(&pidCtrl1, xError1, yError1); controllerCorrectAttitudePID(&pidCtrl1, t.pos[0], t.pos[1], zPosition1, correctedYaw1, xPositionDesired1, yPositionDesired1, zPositionDesired1, yawDesired1, &rollControlOutput1, &pitchControlOutput1, &yawControlOutput1, &thrustControlOutput1); </syntaxhighlight> ::'''Note 1:''' We calculate error externally for X and Y because certain swarm controllers need special setpoint modifiers (this way we can switch modes without effecting the default setpoint): ::'''Note 2:''' Swap out the Controller - all we need to do is create a similar function and replace ''controllerCorrectAttitudePID'' above ::'''Example:''' Follow Hand Mode Error (Crazyflie1 will have setpoint -0.5 m lower in X and +0.5 m higher in Y than your hand trackable): ::<syntaxhighlight lang="cpp"> ... xError1 = (xPositionHand - 0.5) - xPosition1; yError1 = (yPositionHand + 0.5) - yPosition1; controllerSetXYError(&pidCtrl1, xError1, yError1); ... </syntaxhighlight> :4. Send Calculated Control Outputs to the Crazyflie via the Radio (code found in ''simple.cpp''): ::<syntaxhighlight lang="cpp"> RunCrazyflie(crRadio2, cflieCopter3, rollControlOutput3, pitchControlOutput3, yawControlOutput3, thrustControlOutput3); </syntaxhighlight> ::Where the ''RunCrazyflie'' function looks like this (code in ''simple.cpp''): ::<syntaxhighlight lang="cpp"> int RunCrazyflie(CCrazyRadio *crRadio, CCrazyflie *cflieCopter, float rollControl, float pitchControl, float yawControl, float thrustControl) { //Timing Index Variables (**FOR TESTING ROUTINES**) int i = 0; while(cflieCopter->cycle()) { //If Crazyflie is vertical kill motors, Crash Imminent if(cflieCopter->roll() > 90){ cflieCopter->setThrust(10000); } else if(cflieCopter->roll() < -90){ cflieCopter->setThrust(10000); } else if(cflieCopter->pitch() > 90){ cflieCopter->setThrust(10000); } else if(cflieCopter->pitch() < -90){ cflieCopter->setThrust(10000); } //Otherwise Send Setpoints else if(i < 1){ //i < 200000 cflieCopter->setThrust(thrustControl); cflieCopter->setRoll(rollControl); cflieCopter->setPitch(pitchControl); cflieCopter->setYaw(-yawControl); //******SET TO NEGATIVE FOR CAMERA SYSTEM YAW BEING REVERSED!!!!**** i++; } else{ break; } } return 0; } </syntaxhighlight> ::'''IMPORTANT:''' This function contains the function <code>cflieCopter->cycle()</code> which is CRITICAL to maintaining communications with the Crazyflie. The ''cycle'' function initiates communications, sends setpoints, and must be called frequently otherwise the communications will timeout and the Crazyflie will stop as a precaution. :5. Repeat steps 3 through 5 for each set of new location data...until Program END. ===Swapping Client Controller Type=== With the Swarm Platform we can plug any controller (that can be coded in C or C++) into the Client to control the Crazyflies. In steps 1, 2, and 3 of the [[#Calculating the PID's|Calculating the PID's]] section, you can see the whole process of how we calculate the control output. To replace the PID with a different controller we can follow those steps but with our new controller. So as a general idea of the process we have: ('''Note:''' This depends heavily on how your controller works, this is generalized for a single input single output controller) #Implement the New Controller Output Calculation in C as a function #Create multiple instances of this controller calculation function (for each Degree of Freedom (DOF) you need to control) and combine them into a function to calculate all controllers with 1 function call ('''Note:''' This step is for ease of code use, NOT Required) #In each Callback, call the function to Calculate the Controller output. ---- <center> '''Main Directory''' </center> <center> [[Crazyflie Swarm|Crazyflie Swarm Home]] | [[PC Client Software]] | [[USB Radio]] | [[Firmware]] | [[FAQ]] </center> <center> '''Modifications Directory''' </center> <center> [[Controller]] | [[Logging]] | [[Keyboard Commands]] | [[USB Radio#Changing Radio Channel|Changing Radio Channel]] | [[Flight Modes]] | [[Callbacks]] | [[Adding a Crazyflie]] | [[Firmware]] </center> f1fc3f07ef83af4e6569bcdf08f096d97dd9e6ad Distributed Autonomous and Networked Control Lab Wiki 0 1 321 48 2016-09-11T20:41:57Z Jonessk 7 Added a schedule slot wikitext text/x-wiki Welcome to the Distributed Autonomous and Networked Control Lab Wiki! Here you can find a wealth of information regarding the many projects we have running in the Lab. Below are some of the projects we are working on: ''' == Projects == ''' [[Crazyflie Swarm]] [[Robotic Agriculture Data Acquisition (RADA)]] [[MicroCART]] [[Camera System and VRPN]] If you can't find what you're looking for please feel free to contribute. Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Lab Schedule == == Getting Started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] 5386eb9e63fed622def2bd8b8b032690c86b34c3 322 321 2016-09-11T20:56:52Z Jonessk 7 Inserted basic scheduling table wikitext text/x-wiki Welcome to the Distributed Autonomous and Networked Control Lab Wiki! Here you can find a wealth of information regarding the many projects we have running in the Lab. Below are some of the projects we are working on: ''' == Projects == ''' [[Crazyflie Swarm]] [[Robotic Agriculture Data Acquisition (RADA)]] [[MicroCART]] [[Camera System and VRPN]] If you can't find what you're looking for please feel free to contribute. Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Lab Schedule == {| class="wikitable" style="text-align:center" |+Reserved Lab Times |- ! Time !! Monday !! Tuesday !! Wednesday !! Thursday !! Friday |- ! 8am - 9am | Open || Open || Open || Open || Open |- ! 9am - 10am | Open || Open || Open || Open || Open |- ! 10am - 11am | Open || Open || Open || Open || Open |- ! 11am - 12pm | Open || Open || Open || Open || Open |- ! 12pm - 1pm | Open || Open || Open || Open || Open |- ! 1pm - 2pm | Open || Open || Open || Open || Open |- ! 2pm - 3pm | Open || Open || Open || Open || Open |- ! 3pm - 4pm | Open || Open || Open || Open || Open |- ! 4pm - 5pm | RADA || RADA || RADA || Open || Open |- ! 5pm - 6pm | RADA || RADA || RADA || Open || Open |- ! 6pm - 7pm | 1Open || Open || Open || Open || Open |- ! 7pm - 8pm | Open || Open || Open || Open || Open |} == Getting Started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] aa4e6410ac4bcd6d71d6dcb9670c93694d173cf9 323 322 2016-09-11T21:14:47Z Jonessk 7 Formatting changes to schedule wikitext text/x-wiki Welcome to the Distributed Autonomous and Networked Control Lab Wiki! Here you can find a wealth of information regarding the many projects we have running in the Lab. Below are some of the projects we are working on: ''' == Projects == ''' [[Crazyflie Swarm]] [[Robotic Agriculture Data Acquisition (RADA)]] [[MicroCART]] [[Camera System and VRPN]] If you can't find what you're looking for please feel free to contribute. Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Lab Schedule == {| class="wikitable" style="text-align:center" |+Reserved Lab Times |- ! width="100"|Time !! width="100"|Monday !! width="100"|Tuesday !! width="100"|Wednesday !! width="100"|Thursday !! width="100"|Friday |- ! 8am - 9am | Open || Open || Open || Open || Open |- ! 9am - 10am | Open || Open || Open || Open || Open |- ! 10am - 11am | Open || Open || Open || Open || Open |- ! 11am - 12pm | Open || Open || Open || Open || Open |- ! 12pm - 1pm | Open || Open || Open || Open || Open |- ! 1pm - 2pm | Open || Open || Open || Open || Open |- ! 2pm - 3pm | Open || Open || Open || Open || Open |- ! 3pm - 4pm | Open || Open || Open || Open || Open |- ! 4pm - 5pm | style="background:teal"|RADA || style="background:teal"|RADA || style="background:teal"|RADA || Open || Open |- ! 5pm - 6pm | style="background:teal"|RADA || style="background:teal"|RADA || style="background:teal"|RADA || Open || Open |- ! 6pm - 7pm | 1Open || Open || Open || Open || Open |- ! 7pm - 8pm | Open || Open || Open || Open || Open |} == Getting Started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] 56c97d0d496e669b49397b57fa13f69b76a8302c 324 323 2016-09-11T21:15:13Z Jonessk 7 /* Lab Schedule */ wikitext text/x-wiki Welcome to the Distributed Autonomous and Networked Control Lab Wiki! Here you can find a wealth of information regarding the many projects we have running in the Lab. Below are some of the projects we are working on: ''' == Projects == ''' [[Crazyflie Swarm]] [[Robotic Agriculture Data Acquisition (RADA)]] [[MicroCART]] [[Camera System and VRPN]] If you can't find what you're looking for please feel free to contribute. Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Lab Schedule == {| class="wikitable" style="text-align:center" |+Reserved Lab Times |- ! width="100"|Time !! width="100"|Monday !! width="100"|Tuesday !! width="100"|Wednesday !! width="100"|Thursday !! width="100"|Friday |- ! 8am - 9am | Open || Open || Open || Open || Open |- ! 9am - 10am | Open || Open || Open || Open || Open |- ! 10am - 11am | Open || Open || Open || Open || Open |- ! 11am - 12pm | Open || Open || Open || Open || Open |- ! 12pm - 1pm | Open || Open || Open || Open || Open |- ! 1pm - 2pm | Open || Open || Open || Open || Open |- ! 2pm - 3pm | Open || Open || Open || Open || Open |- ! 3pm - 4pm | Open || Open || Open || Open || Open |- ! 4pm - 5pm | style="background:teal"|RADA || style="background:teal"|RADA || style="background:teal"|RADA || Open || Open |- ! 5pm - 6pm | style="background:teal"|RADA || style="background:teal"|RADA || style="background:teal"|RADA || Open || Open |- ! 6pm - 7pm | Open || Open || Open || Open || Open |- ! 7pm - 8pm | Open || Open || Open || Open || Open |} == Getting Started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] 0b8b4c2f77c32dd3f565e6ee3ac273cceabe037b 325 324 2016-09-15T16:46:01Z Jonessk 7 wikitext text/x-wiki Welcome to the Distributed Autonomous and Networked Control Lab Wiki! Here you can find a wealth of information regarding the many projects we have running in the Lab. Below are some of the projects we are working on: ''' == Projects == ''' [[Crazyflie Swarm]] [[Robotic Agriculture Data Acquisition (RADA)]] [[MicroCART]] [[Camera System and VRPN]] If you can't find what you're looking for please feel free to contribute. Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Lab Schedule == {| class="wikitable" style="text-align:center" |+Reserved Lab Times |- ! width="110"|Time !! width="110"|Monday !! width="110"|Tuesday !! width="110"|Wednesday !! width="110"|Thursday !! width="110"|Friday |- ! 8am - 9am | Open || Open || Open || Open || Open |- ! 9am - 10am | Open || Open || Open || Open || Open |- ! 10am - 11am | Open || Open || Open || Open || Open |- ! 11am - 12pm | Open || Open || Open || Open || Open |- ! 12pm - 1pm | Open || Open || Open || Open || Open |- ! 1pm - 2pm | Open || Open || Open || Open || Open |- ! 2pm - 3pm | Open || Open || Open || Open || Open |- ! 3pm - 4pm | Open || Open || Open || Open || Open |- ! 4pm - 5pm | style="background:orange"|CrazyFlie Meeting || style="background:teal"|RADA || style="background:teal"|RADA Meeting || Open || Open |- ! 5pm - 6pm | style="background:teal"|RADA || style="background:teal"|RADA || style="background:teal"|RADA || Open || Open |- ! 6pm - 7pm | Open || Open || Open || Open || Open |- ! 7pm - 8pm | Open || Open || Open || Open || Open |} == Getting Started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] af383122049a2fafa439bba4752765b6381cf22f 326 325 2016-09-21T01:58:54Z Snawerdt 8 wikitext text/x-wiki Welcome to the Distributed Autonomous and Networked Control Lab Wiki! Here you can find a wealth of information regarding the many projects we have running in the Lab. Below are some of the projects we are working on: ''' == Projects == ''' [[Crazyflie Swarm]] [[Robotic Agriculture Data Acquisition (RADA)]] [[MicroCART]] [[Camera System and VRPN]] If you can't find what you're looking for please feel free to contribute. Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Lab Schedule == {| class="wikitable" style="text-align:center" |+Reserved Lab Times |- ! width="110"|Time !! width="110"|Monday !! width="110"|Tuesday !! width="110"|Wednesday !! width="110"|Thursday !! width="110"|Friday |- ! 8am - 9am | Open || Open || Open || Open || Open |- ! 9am - 10am | Open || Open || Open || Open || Open |- ! 10am - 11am | Open || Open || Open || Open || Open |- ! 11am - 12pm | Open || Open || Open || Open || Open |- ! 12pm - 1pm | Open || Open || Open || Open || Open |- ! 1pm - 2pm | Open || Open || Open || Open || Open |- ! 2pm - 3pm | Open || Open || Open || Open || Open |- ! 3pm - 4pm | Open || Open || Open || Open || Open |- ! 4pm - 5pm | style="background:orange"|CrazyFlie Meeting || style="background:teal"|RADA || style="background:teal"|RADA Meeting || Open || Open |- ! 5pm - 6pm | style="background:teal"|RADA || style="background:teal"|RADA || style="background:teal"|RADA || Open || Open |- ! 6pm - 7pm | Open || Open || Open || Open || Open |- ! 7pm - 8pm | Open || Open || Open || Open || Open |- ! 8pm - 9pm | Open || Open || Open || Open || Open |- ! 9pm - 10pm | Open || Open || Open || Open || Open |} == Getting Started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] 6f467e272bc2f006b5fe3f0b6d3eadf87d4af155 327 326 2016-09-21T02:04:03Z Snawerdt 8 wikitext text/x-wiki Welcome to the Distributed Autonomous and Networked Control Lab Wiki! Here you can find a wealth of information regarding the many projects we have running in the Lab. Below are some of the projects we are working on: ''' == Projects == ''' [[Crazyflie Swarm]] [[Robotic Agriculture Data Acquisition (RADA)]] [[MicroCART]] [[Camera System and VRPN]] If you can't find what you're looking for please feel free to contribute. Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Lab Schedule == {| class="wikitable" style="text-align:center" |+Reserved Lab Times |- ! width="110"|Time !! width="110"|Monday !! width="110"|Tuesday !! width="110"|Wednesday !! width="110"|Thursday !! width="110"|Friday |- ! 8am - 9am | Open || Open || Open || Open || Open |- ! 9am - 10am | Open || Open || Open || Open || Open |- ! 10am - 11am | Open || Open || Open || Open || Open |- ! 11am - 12pm | Open || Open || Open || Open || Open |- ! 12pm - 1pm | Open || Open || Open || Open || Open |- ! 1pm - 2pm | Open || style="background:green"|MicroCART Meeting || Open || Open || Open |- ! 2pm - 3pm | Open || Open || Open || Open || Open |- ! 3pm - 4pm | Open || Open || Open || style="background:green"|MicroCART || Open |- ! 4pm - 5pm | style="background:orange"|CrazyFlie Meeting || style="background:teal"|RADA || style="background:teal"|RADA Meeting || style="background:green"|MicroCART || style="background:green"|MicroCART |- ! 5pm - 6pm | style="background:teal"|RADA || style="background:teal"|RADA || style="background:teal"|RADA || Open || style="background:green"|MicroCART |- ! 6pm - 7pm | Open || Open || Open || Open || Open |- ! 7pm - 8pm | Open || Open || Open || Open || Open |- ! 8pm - 9pm | Open || Open || Open || Open || Open |- ! 9pm - 10pm | Open || Open || Open || Open || Open |} == Getting Started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] 031193229ddc90ee7ff8aec46ee1f432b4abf71f 342 327 2016-09-26T17:12:00Z Coleb 9 /* Lab Schedule */ wikitext text/x-wiki Welcome to the Distributed Autonomous and Networked Control Lab Wiki! Here you can find a wealth of information regarding the many projects we have running in the Lab. Below are some of the projects we are working on: ''' == Projects == ''' [[Crazyflie Swarm]] [[Robotic Agriculture Data Acquisition (RADA)]] [[MicroCART]] [[Camera System and VRPN]] If you can't find what you're looking for please feel free to contribute. Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Lab Schedule == {| class="wikitable" style="text-align:center" |+Reserved Lab Times |- ! width="110"|Time !! width="110"|Monday !! width="110"|Tuesday !! width="110"|Wednesday !! width="110"|Thursday !! width="110"|Friday |- ! 8am - 9am | Open || Open || Open || Open || Open |- ! 9am - 10am | Open || Open || Open || Open || Open |- ! 10am - 11am | Open || Open || Open || Open || Open |- ! 11am - 12pm | Open || style="background:orange"|CrazyFlie || Open || Open || Open |- ! 12pm - 1pm | Open || style="background:orange"|CrazyFlie|| Open || style="background:orange"|CrazyFlie || Open |- ! 1pm - 2pm | Open || style="background:green"|MicroCART Meeting || style="background:orange"|CrazyFlie || style="background:orange"|CrazyFlie || Open |- ! 2pm - 3pm | Open || Open ||style="background:orange"|CrazyFlie Meeting || style="background:orange"|CrazyFlie || Open |- ! 3pm - 4pm | Open || Open || Open || style="background:green"|MicroCART || Open |- ! 4pm - 5pm | style="background:orange"|CrazyFlie Meeting || style="background:teal"|RADA || style="background:teal"|RADA Meeting || style="background:green"|MicroCART || style="background:green"|MicroCART |- ! 5pm - 6pm | style="background:teal"|RADA || style="background:teal"|RADA || style="background:teal"|RADA || Open || style="background:green"|MicroCART |- ! 6pm - 7pm | Open || Open || Open || Open || Open |- ! 7pm - 8pm | Open || Open || Open || Open || Open |- ! 8pm - 9pm | Open || Open || Open || Open || Open |- ! 9pm - 10pm | Open || Open || Open || Open || Open |} == Getting Started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] fb4b05c1add4d473da3f5808de6392ef80762325 343 342 2016-09-26T17:12:42Z Coleb 9 /* Lab Schedule */ wikitext text/x-wiki Welcome to the Distributed Autonomous and Networked Control Lab Wiki! Here you can find a wealth of information regarding the many projects we have running in the Lab. Below are some of the projects we are working on: ''' == Projects == ''' [[Crazyflie Swarm]] [[Robotic Agriculture Data Acquisition (RADA)]] [[MicroCART]] [[Camera System and VRPN]] If you can't find what you're looking for please feel free to contribute. Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Lab Schedule == {| class="wikitable" style="text-align:center" |+Reserved Lab Times |- ! width="110"|Time !! width="110"|Monday !! width="110"|Tuesday !! width="110"|Wednesday !! width="110"|Thursday !! width="110"|Friday |- ! 8am - 9am | Open || Open || Open || Open || Open |- ! 9am - 10am | Open || Open || Open || Open || Open |- ! 10am - 11am | Open || Open || Open || Open || Open |- ! 11am - 12pm | Open || style="background:orange"|CrazyFlie || Open || Open || Open |- ! 12pm - 1pm | Open || style="background:orange"|CrazyFlie|| Open || style="background:orange"|CrazyFlie || Open |- ! 1pm - 2pm | Open || style="background:green"|MicroCART Meeting || style="background:orange"|CrazyFlie || style="background:orange"|CrazyFlie || Open |- ! 2pm - 3pm | Open || Open ||style="background:orange"|CrazyFlie || style="background:orange"|CrazyFlie || Open |- ! 3pm - 4pm | Open || Open || style="background:orange"|CrazyFlie || style="background:green"|MicroCART || Open |- ! 4pm - 5pm | style="background:orange"|CrazyFlie Meeting || style="background:teal"|RADA || style="background:teal"|RADA Meeting || style="background:green"|MicroCART || style="background:green"|MicroCART |- ! 5pm - 6pm | style="background:teal"|RADA || style="background:teal"|RADA || style="background:teal"|RADA || Open || style="background:green"|MicroCART |- ! 6pm - 7pm | Open || Open || Open || Open || Open |- ! 7pm - 8pm | Open || Open || Open || Open || Open |- ! 8pm - 9pm | Open || Open || Open || Open || Open |- ! 9pm - 10pm | Open || Open || Open || Open || Open |} == Getting Started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] 58473be9c24f8992845300861999c12460e56695 347 343 2016-09-26T22:02:17Z Coleb 9 /* Lab Schedule */ wikitext text/x-wiki Welcome to the Distributed Autonomous and Networked Control Lab Wiki! Here you can find a wealth of information regarding the many projects we have running in the Lab. Below are some of the projects we are working on: ''' == Projects == ''' [[Crazyflie Swarm]] [[Robotic Agriculture Data Acquisition (RADA)]] [[MicroCART]] [[Camera System and VRPN]] If you can't find what you're looking for please feel free to contribute. Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Lab Schedule == {| class="wikitable" style="text-align:center" |+Reserved Lab Times |- ! width="110"|Time !! width="110"|Monday !! width="110"|Tuesday !! width="110"|Wednesday !! width="110"|Thursday !! width="110"|Friday |- ! 8am - 9am | Open || Open || Open || Open || Open |- ! 9am - 10am | Open || Open || Open || Open || Open |- ! 10am - 11am | Open || style="background:orange"|CrazyFlie || Open || Open || Open |- ! 11am - 12pm | Open || style="background:orange"|CrazyFlie || Open || Open || Open |- ! 12pm - 1pm | Open || style="background:orange"|CrazyFlie|| Open || style="background:orange"|CrazyFlie || Open |- ! 1pm - 2pm | Open || style="background:green"|MicroCART Meeting || style="background:orange"|CrazyFlie || style="background:orange"|CrazyFlie || Open |- ! 2pm - 3pm | Open || Open ||style="background:orange"|CrazyFlie || style="background:orange"|CrazyFlie || Open |- ! 3pm - 4pm | Open || Open || style="background:orange"|CrazyFlie || style="background:green"|MicroCART || Open |- ! 4pm - 5pm | style="background:orange"|CrazyFlie Meeting || style="background:teal"|RADA || style="background:teal"|RADA Meeting || style="background:green"|MicroCART || style="background:green"|MicroCART |- ! 5pm - 6pm | style="background:teal"|RADA || style="background:teal"|RADA || style="background:teal"|RADA || Open || style="background:green"|MicroCART |- ! 6pm - 7pm | Open || Open || Open || Open || Open |- ! 7pm - 8pm | Open || Open || Open || Open || Open |- ! 8pm - 9pm | Open || Open || Open || Open || Open |- ! 9pm - 10pm | Open || Open || Open || Open || Open |} == Getting Started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] a0d335e0f412f7ebd8fa1ee959f3b67a2a6eda6b 348 347 2016-10-03T20:07:36Z Jonessk 7 /* Lab Schedule */ wikitext text/x-wiki Welcome to the Distributed Autonomous and Networked Control Lab Wiki! Here you can find a wealth of information regarding the many projects we have running in the Lab. Below are some of the projects we are working on: ''' == Projects == ''' [[Crazyflie Swarm]] [[Robotic Agriculture Data Acquisition (RADA)]] [[MicroCART]] [[Camera System and VRPN]] If you can't find what you're looking for please feel free to contribute. Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Lab Schedule == {| class="wikitable" style="text-align:center" |+Reserved Lab Times |- ! width="110"|Time !! width="110"|Monday !! width="110"|Tuesday !! width="110"|Wednesday !! width="110"|Thursday !! width="110"|Friday |- ! 8am - 9am | Open || Open || Open || Open || Open |- ! 9am - 10am | Open || Open || Open || Open || Open |- ! 10am - 11am | Open || style="background:orange"|CrazyFlie || Open || Open || Open |- ! 11am - 12pm | Open || style="background:orange"|CrazyFlie || Open || Open || Open |- ! 12pm - 1pm | Open || style="background:orange"|CrazyFlie|| Open || style="background:orange"|CrazyFlie || Open |- ! 1pm - 2pm | Open || style="background:green"|MicroCART Meeting || style="background:orange"|CrazyFlie || style="background:orange"|CrazyFlie || Open |- ! 2pm - 3pm | Open || Open ||style="background:orange"|CrazyFlie || style="background:orange"|CrazyFlie || Open |- ! 3pm - 4pm | Open || Open || style="background:orange"|CrazyFlie || style="background:green"|MicroCART || Open |- ! 4pm - 5pm | style="background:orange"|CrazyFlie Meeting || style="background:teal"|RADA || style="background:teal"|RADA Meeting || style="background:green"|MicroCART || style="background:green"|MicroCART |- ! 5pm - 6pm | style="background:teal"|RADA || style="background:teal"|RADA || style="background:teal"|RADA || Open || style="background:green"|MicroCART |- ! 6pm - 7pm | style="background:teal"|RADA || style="background:teal"|RADA || style="background:teal"|RADA || Open || Open |- ! 7pm - 8pm | Open || Open || Open || Open || Open |- ! 8pm - 9pm | Open || Open || Open || Open || Open |- ! 9pm - 10pm | Open || Open || Open || Open || Open |} == Getting Started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] 0bf0b39982da2c0210754d792de553a13be91238 349 348 2016-10-07T05:16:02Z Jonessk 7 wikitext text/x-wiki Welcome to the Distributed Autonomous and Networked Control Lab Wiki! Here you can find a wealth of information regarding the many projects we have running in the Lab. Below are some of the projects we are working on: ''' == Projects == ''' [[Crazyflie Swarm]] [[Robotic Agriculture Data Acquisition (RADA)]] [[MicroCART]] [[Camera System and VRPN]] If you can't find what you're looking for please feel free to contribute. Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Lab Schedule == {| class="wikitable" style="text-align:center" |+Reserved Lab Times |- ! width="130"|Time !! width="130"|Monday !! width="130"|Tuesday !! width="130"|Wednesday !! width="130"|Thursday !! width="130"|Friday |- ! 8am - 9am | Open || Open || Open || Open || Open |- ! 9am - 10am | Open || Open || Open || Open || Open |- ! 10am - 11am | Open || style="background:orange"|CrazyFlie || Open || Open || Open |- ! 11am - 12pm | Open || style="background:orange"|CrazyFlie || Open || Open || Open |- ! 12pm - 1pm | Open || style="background:orange"|CrazyFlie|| Open || style="background:orange"|CrazyFlie || Open |- ! 1pm - 2pm | Open || style="background:green"|MicroCART Meeting || style="background:orange"|CrazyFlie || style="background:orange"|CrazyFlie || Open |- ! 2pm - 3pm | Open || Open ||style="background:orange"|CrazyFlie || style="background:orange"|CrazyFlie || Open |- ! 3pm - 4pm | Open || Open || style="background:orange"|CrazyFlie || style="background:green"|MicroCART || Open |- ! 4pm - 5pm | style="background:orange"|CrazyFlie Meeting || style="background:teal"|RADA || style="background:teal"|RADA Meeting || style="background:green"|MicroCART || style="background:green"|MicroCART |- ! 5pm - 6pm | style="background:teal"|RADA || style="background:teal"|RADA || style="background:teal"|RADA || Open || style="background:green"|MicroCART |- ! 6pm - 7pm | style="background:teal"|RADA || style="background:teal"|RADA || style="background:teal"|RADA || Open || Open |- ! 7pm - 8pm | Open || Open || Open || Open || Open |- ! 8pm - 9pm | Open || Open || Open || Open || Open |- ! 9pm - 10pm | Open || Open || Open || Open || Open |} == Getting Started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] 6d1e41290419fc455e438e19e82f812e416055e8 350 349 2016-10-13T16:01:44Z Imciner2 6 wikitext text/x-wiki Welcome to the Distributed Autonomous and Networked Control Lab Wiki! Here you can find a wealth of information regarding the many projects we have running in the Lab. Below are some of the projects we are working on: ''' == Projects == ''' [[Crazyflie Swarm]] [[Robotic Agriculture Data Acquisition (RADA)]] [[MicroCART]] [[Camera System and VRPN]] ''' == Lab-Wide Information == [[Physical Parameters]] - Physical parameters for systems in the laboratory If you can't find what you're looking for please feel free to contribute. Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Lab Schedule == {| class="wikitable" style="text-align:center" |+Reserved Lab Times |- ! width="130"|Time !! width="130"|Monday !! width="130"|Tuesday !! width="130"|Wednesday !! width="130"|Thursday !! width="130"|Friday |- ! 8am - 9am | Open || Open || Open || Open || Open |- ! 9am - 10am | Open || Open || Open || Open || Open |- ! 10am - 11am | Open || style="background:orange"|CrazyFlie || Open || Open || Open |- ! 11am - 12pm | Open || style="background:orange"|CrazyFlie || Open || Open || Open |- ! 12pm - 1pm | Open || style="background:orange"|CrazyFlie|| Open || style="background:orange"|CrazyFlie || Open |- ! 1pm - 2pm | Open || style="background:green"|MicroCART Meeting || style="background:orange"|CrazyFlie || style="background:orange"|CrazyFlie || Open |- ! 2pm - 3pm | Open || Open ||style="background:orange"|CrazyFlie || style="background:orange"|CrazyFlie || Open |- ! 3pm - 4pm | Open || Open || style="background:orange"|CrazyFlie || style="background:green"|MicroCART || Open |- ! 4pm - 5pm | style="background:orange"|CrazyFlie Meeting || style="background:teal"|RADA || style="background:teal"|RADA Meeting || style="background:green"|MicroCART || style="background:green"|MicroCART |- ! 5pm - 6pm | style="background:teal"|RADA || style="background:teal"|RADA || style="background:teal"|RADA || Open || style="background:green"|MicroCART |- ! 6pm - 7pm | style="background:teal"|RADA || style="background:teal"|RADA || style="background:teal"|RADA || Open || Open |- ! 7pm - 8pm | Open || Open || Open || Open || Open |- ! 8pm - 9pm | Open || Open || Open || Open || Open |- ! 9pm - 10pm | Open || Open || Open || Open || Open |} == Getting Started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] aa2e49dba8aec2e45a65b9e19bec5cc7fc86f3f3 File:ErisOnPhoto.jpg 6 62 334 216 2016-09-21T23:17:53Z Jonessk 7 Jonessk uploaded a new version of [[File:ErisOnPhoto.jpg]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 335 334 2016-09-21T23:22:02Z Jonessk 7 Jonessk uploaded a new version of [[File:ErisOnPhoto.jpg]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 336 335 2016-09-21T23:23:10Z Jonessk 7 Jonessk uploaded a new version of [[File:ErisOnPhoto.jpg]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Physical Parameters 0 83 351 2016-10-13T16:06:05Z Imciner2 6 Added motor information wikitext text/x-wiki == Motor/Propeller Information == {| class="wikitable" |+Motor Information |- | |Kv (RPM) |Kv (rad/sec) |Kq (rad/sec) |If (A) |Rm (Ohms) |- |DJI Opto 30A Old Motor |920 |96.3422 |96.3422 |0.422 |0.243 |- |DJI Opto 30A New Motor |920 |96.3422 |96.3422 |0.511 |TBD |} 03ecd6a99f1ea8049c801ad9c9d24fefa45ec58d 352 351 2016-10-13T16:12:54Z Imciner2 6 Added propeller information wikitext text/x-wiki == Motor/Propeller Information == {| class="wikitable" |+Motor Information |- | |Kv (RPM) |Kv (rad/sec) |Kq (rad/sec) |If (A) |Rm (Ohms) |- |DJI Opto 30A Old Motor |920 |96.3422 |96.3422 |0.422 |0.243 |- |DJI Opto 30A New Motor |920 |96.3422 |96.3422 |0.511 |TBD |} {| class="wikitable" |+Propeller Information |- | |Kt (kgm/rad^2) |Kd (kgm^2/rad^2) |- |DJI 8045 8in |2.3765E-07 |7.9008E-06 |- |DJI 9443 9in |9.5705E-06 |TBD |- |Carbon Fiber 9in |1.2364E-05 |2.9011E-07 |- |DJI 1045 10in |1.1325E-05 |3.5388E-07 |} e67b603f38c24d19028d3c6e7efa35cccd395fbc 353 352 2016-10-13T16:23:51Z Imciner2 6 Added system information wikitext text/x-wiki == Motor Information == {| class="wikitable" |+Motor Information |- | |Kv (RPM) |Kv (rad/sec) |Kq (rad/sec) |If (A) |Rm (Ohms) |- |DJI 2212/920 Old Motor |920 |96.3422 |96.3422 |0.422 |0.243 |- |DJI 2212/920 New Motor |920 |96.3422 |96.3422 |0.511 |TBD |} == Propeller Information == {| class="wikitable" |+Propeller Information |- | |Kt (kgm/rad^2) |Kd (kgm^2/rad^2) |- |DJI 8045 8in |2.3765e-07 |7.9008e-06 |- |DJI 9443 9in |9.5705e-06 |TBD |- |Carbon Fiber 9in |1.2364e-05 |2.9011e-07 |- |DJI 1045 10in |1.1325e-05 |3.5388e-07 |} == Motor & Propeller System Information == {| class="wikitable" |+Propeller Information |- | |Tau (sec) |Jr (kgm^2) |- |DJI 2212/920 New w/ 9445 Propeller & Standard ESC |0.09 |TBD |- |DJI 2212/920 Old w/ 8045 Propeller & Standard ESC |0.12 |5.3204e-05 |- |DJI 2212/920 Old w/ 1045 Propeller & Standard ESC |0.14 |6.2071e-05 |- |DJI 2212/920 Old w/ 10in Carbon Fiber Propeller & Standard ESC |0.24 |1.0641e-04 |} d0be23bd8d45c24dd0f7062091ae8b18377f2d55 354 353 2016-10-13T16:25:25Z Imciner2 6 /* Motor & Propeller System Information */ wikitext text/x-wiki == Motor Information == {| class="wikitable" |+Motor Information |- | |Kv (RPM) |Kv (rad/sec) |Kq (rad/sec) |If (A) |Rm (Ohms) |- |DJI 2212/920 Old Motor |920 |96.3422 |96.3422 |0.422 |0.243 |- |DJI 2212/920 New Motor |920 |96.3422 |96.3422 |0.511 |TBD |} == Propeller Information == {| class="wikitable" |+Propeller Information |- | |Kt (kgm/rad^2) |Kd (kgm^2/rad^2) |- |DJI 8045 8in |2.3765e-07 |7.9008e-06 |- |DJI 9443 9in |9.5705e-06 |TBD |- |Carbon Fiber 9in |1.2364e-05 |2.9011e-07 |- |DJI 1045 10in |1.1325e-05 |3.5388e-07 |} == Motor & Propeller System Information == {| class="wikitable" |+Propeller Information |- | |Tau (sec) |Jr (kgm^2) |- |DJI 2212/920 New w/ 9445 Propeller & New DJI Opto 30A ESC |0.09 |TBD |- |DJI 2212/920 Old w/ 8045 Propeller & Old DJI Opto 30A ESC |0.12 |5.3204e-05 |- |DJI 2212/920 Old w/ 1045 Propeller & Old DJI Opto 30A ESC |0.14 |6.2071e-05 |- |DJI 2212/920 Old w/ 10in Carbon Fiber Propeller & Old DJI Opto 30A ESC |0.24 |1.0641e-04 |} 72abc9623f358e87f40f0a0a00ca10b3702bfced 355 354 2016-10-17T20:13:13Z Snawerdt 8 /* Motor Information */ wikitext text/x-wiki == Motor Information == {| class="wikitable" |+Motor Information |- | |Kv (RPM) |Kv (rad/sec) |Kq (rad/sec) |If (A) |Rm (Ohms) |- |DJI 2212/920 Old Motor |920 |96.3422 |96.3422 |0.422 |0.243 |- |DJI 2212/920 New Motor |920 |96.3422 |96.3422 |0.511 |0.2308 |} == Propeller Information == {| class="wikitable" |+Propeller Information |- | |Kt (kgm/rad^2) |Kd (kgm^2/rad^2) |- |DJI 8045 8in |2.3765e-07 |7.9008e-06 |- |DJI 9443 9in |9.5705e-06 |TBD |- |Carbon Fiber 9in |1.2364e-05 |2.9011e-07 |- |DJI 1045 10in |1.1325e-05 |3.5388e-07 |} == Motor & Propeller System Information == {| class="wikitable" |+Propeller Information |- | |Tau (sec) |Jr (kgm^2) |- |DJI 2212/920 New w/ 9445 Propeller & New DJI Opto 30A ESC |0.09 |TBD |- |DJI 2212/920 Old w/ 8045 Propeller & Old DJI Opto 30A ESC |0.12 |5.3204e-05 |- |DJI 2212/920 Old w/ 1045 Propeller & Old DJI Opto 30A ESC |0.14 |6.2071e-05 |- |DJI 2212/920 Old w/ 10in Carbon Fiber Propeller & Old DJI Opto 30A ESC |0.24 |1.0641e-04 |} e4bffd50f722bdc2719908ffc1c5dae1696643a1 356 355 2016-10-18T20:27:51Z Imciner2 6 Added propeller constants for 9in DJI. wikitext text/x-wiki == Motor Information == {| class="wikitable" |+Motor Information |- | |Kv (RPM) |Kv (rad/sec) |Kq (rad/sec) |If (A) |Rm (Ohms) |- |DJI 2212/920 Old Motor |920 |96.3422 |96.3422 |0.422 |0.243 |- |DJI 2212/920 New Motor |920 |96.3422 |96.3422 |0.511 |0.2308 |} == Propeller Information == {| class="wikitable" |+Propeller Information |- | |Kt (kgm/rad^2) |Kd (kgm^2/rad^2) |- |DJI 8045 8in |2.3765e-07 |7.9008e-06 |- |DJI 9443 9in |9.5705e-06 |6.1230e-06 |- |Carbon Fiber 9in |1.2364e-05 |2.9011e-07 |- |DJI 1045 10in |1.1325e-05 |3.5388e-07 |} == Motor & Propeller System Information == {| class="wikitable" |+Propeller Information |- | |Tau (sec) |Jr (kgm^2) |- |DJI 2212/920 New w/ 9445 Propeller & New DJI Opto 30A ESC |0.09 |4.2012e-05 |- |DJI 2212/920 Old w/ 8045 Propeller & Old DJI Opto 30A ESC |0.12 |5.3204e-05 |- |DJI 2212/920 Old w/ 1045 Propeller & Old DJI Opto 30A ESC |0.14 |6.2071e-05 |- |DJI 2212/920 Old w/ 10in Carbon Fiber Propeller & Old DJI Opto 30A ESC |0.24 |1.0641e-04 |} c2380023128ebb8fc7a0a7914aee758651185968 360 356 2017-02-21T19:36:59Z M87rich 11 /* Motor Information */ wikitext text/x-wiki == Motor Information == {| class="wikitable" |+Motor Information |- | |Kv (RPM) |Kv (rad/sec) |Kq (rad/sec) |<math>i_{f}</math> (A) |Rm (Ohms) |- |DJI 2212/920 Old Motor |920 |96.3422 |96.3422 |0.422 |0.243 |- |DJI 2212/920 New Motor |920 |96.3422 |96.3422 |0.511 |0.2308 |} == Propeller Information == {| class="wikitable" |+Propeller Information |- | |Kt (kgm/rad^2) |Kd (kgm^2/rad^2) |- |DJI 8045 8in |2.3765e-07 |7.9008e-06 |- |DJI 9443 9in |9.5705e-06 |6.1230e-06 |- |Carbon Fiber 9in |1.2364e-05 |2.9011e-07 |- |DJI 1045 10in |1.1325e-05 |3.5388e-07 |} == Motor & Propeller System Information == {| class="wikitable" |+Propeller Information |- | |Tau (sec) |Jr (kgm^2) |- |DJI 2212/920 New w/ 9445 Propeller & New DJI Opto 30A ESC |0.09 |4.2012e-05 |- |DJI 2212/920 Old w/ 8045 Propeller & Old DJI Opto 30A ESC |0.12 |5.3204e-05 |- |DJI 2212/920 Old w/ 1045 Propeller & Old DJI Opto 30A ESC |0.14 |6.2071e-05 |- |DJI 2212/920 Old w/ 10in Carbon Fiber Propeller & Old DJI Opto 30A ESC |0.24 |1.0641e-04 |} be610fccf6b06c96571d1e29096ca1f3cb516f06 Distributed Autonomous and Networked Control Lab Wiki 0 1 357 350 2016-11-01T18:26:51Z Dawehr 10 /* Projects */ wikitext text/x-wiki Welcome to the Distributed Autonomous and Networked Control Lab Wiki! Here you can find a wealth of information regarding the many projects we have running in the Lab. Below are some of the projects we are working on: ''' == Projects == ''' [[Crazyflie Swarm]] [[Robotic Agriculture Data Acquisition (RADA)]] [https://wikis.ece.iastate.edu/microcart-senior-design/index.php/Main_Page MicroCART] [[Camera System and VRPN]] ''' == Lab-Wide Information == [[Physical Parameters]] - Physical parameters for systems in the laboratory If you can't find what you're looking for please feel free to contribute. Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Lab Schedule == {| class="wikitable" style="text-align:center" |+Reserved Lab Times |- ! width="130"|Time !! width="130"|Monday !! width="130"|Tuesday !! width="130"|Wednesday !! width="130"|Thursday !! width="130"|Friday |- ! 8am - 9am | Open || Open || Open || Open || Open |- ! 9am - 10am | Open || Open || Open || Open || Open |- ! 10am - 11am | Open || style="background:orange"|CrazyFlie || Open || Open || Open |- ! 11am - 12pm | Open || style="background:orange"|CrazyFlie || Open || Open || Open |- ! 12pm - 1pm | Open || style="background:orange"|CrazyFlie|| Open || style="background:orange"|CrazyFlie || Open |- ! 1pm - 2pm | Open || style="background:green"|MicroCART Meeting || style="background:orange"|CrazyFlie || style="background:orange"|CrazyFlie || Open |- ! 2pm - 3pm | Open || Open ||style="background:orange"|CrazyFlie || style="background:orange"|CrazyFlie || Open |- ! 3pm - 4pm | Open || Open || style="background:orange"|CrazyFlie || style="background:green"|MicroCART || Open |- ! 4pm - 5pm | style="background:orange"|CrazyFlie Meeting || style="background:teal"|RADA || style="background:teal"|RADA Meeting || style="background:green"|MicroCART || style="background:green"|MicroCART |- ! 5pm - 6pm | style="background:teal"|RADA || style="background:teal"|RADA || style="background:teal"|RADA || Open || style="background:green"|MicroCART |- ! 6pm - 7pm | style="background:teal"|RADA || style="background:teal"|RADA || style="background:teal"|RADA || Open || Open |- ! 7pm - 8pm | Open || Open || Open || Open || Open |- ! 8pm - 9pm | Open || Open || Open || Open || Open |- ! 9pm - 10pm | Open || Open || Open || Open || Open |} == Getting Started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] 95f93bd1b5a3972912ed205e655f1f4020c78f06 366 357 2017-09-18T21:50:54Z Rbuckley 12 /* Lab Schedule */ wikitext text/x-wiki Welcome to the Distributed Autonomous and Networked Control Lab Wiki! Here you can find a wealth of information regarding the many projects we have running in the Lab. Below are some of the projects we are working on: ''' == Projects == ''' [[Crazyflie Swarm]] [[Robotic Agriculture Data Acquisition (RADA)]] [https://wikis.ece.iastate.edu/microcart-senior-design/index.php/Main_Page MicroCART] [[Camera System and VRPN]] ''' == Lab-Wide Information == [[Physical Parameters]] - Physical parameters for systems in the laboratory If you can't find what you're looking for please feel free to contribute. Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Lab Schedule == {| class="wikitable" style="text-align:center" |+Reserved Lab Times |- ! width="130"|Time !! width="130"|Monday !! width="130"|Tuesday !! width="130"|Wednesday !! width="130"|Thursday !! width="130"|Friday |- ! 8am - 9am | Open || Open || Open || Open || Open |- ! 9am - 10am | Open || Open || Open || Open || Open |- ! 10am - 11am | Open || Open || Open || Open || Open |- ! 11am - 12pm | Open || Open || Open || Open || Open |- ! 12pm - 1pm | Open || Open || Open || open || Open |- ! 1pm - 2pm | Open || Open || Open || Open || Open |- ! 2pm - 3pm | Open || Open || Open || style="background:green"| Meeting || Open |- ! 3pm - 4pm | Open || Open || Open || style="background:green"| Meeting || Open |- ! 4pm - 5pm | Open || style="background:green"|MicroCART Meeting || Open || Open || style="background:green"| Meeting |- ! 5pm - 6pm | Open || Open || Open || Open || style="background:green"| Meeting |- ! 6pm - 7pm | Open || Open || Open || Open || style="background:green"| Meeting |- ! 7pm - 8pm | Open || Open || Open || Open || style="background:green"| Meeting |- ! 8pm - 9pm | Open || Open || Open || Open || style="background:green"| Meeting |- ! 9pm - 10pm | Open || Open || Open || Open || style="background:green"| Meeting |} == Getting Started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] 7132d3dcbacaf7fe262599654c61426920851120 367 366 2017-09-18T21:52:59Z Rbuckley 12 /* Lab Schedule */ wikitext text/x-wiki Welcome to the Distributed Autonomous and Networked Control Lab Wiki! Here you can find a wealth of information regarding the many projects we have running in the Lab. Below are some of the projects we are working on: ''' == Projects == ''' [[Crazyflie Swarm]] [[Robotic Agriculture Data Acquisition (RADA)]] [https://wikis.ece.iastate.edu/microcart-senior-design/index.php/Main_Page MicroCART] [[Camera System and VRPN]] ''' == Lab-Wide Information == [[Physical Parameters]] - Physical parameters for systems in the laboratory If you can't find what you're looking for please feel free to contribute. Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Lab Schedule == {| class="wikitable" style="text-align:center" |+Reserved Lab Times |- ! width="130"|Time !! width="130"|Monday !! width="130"|Tuesday !! width="130"|Wednesday !! width="130"|Thursday !! width="130"|Friday |- ! 8am - 9am | Open || Open || Open || Open || Open |- ! 9am - 10am | Open || Open || Open || Open || Open |- ! 10am - 11am | Open || Open || Open || Open || Open |- ! 11am - 12pm | Open || Open || Open || Open || Open |- ! 12pm - 1pm | Open || Open || Open || open || Open |- ! 1pm - 2pm | Open || Open || Open || Open || Open |- ! 2pm - 3pm | Open || Open || Open || style="background:green"| MicroCART || Open |- ! 3pm - 4pm | Open || Open || Open || style="background:green"| MicroCART || Open |- ! 4pm - 5pm | Open || style="background:green"|MicroCART Meeting || Open || Open || style="background:green"| MicroCART |- ! 5pm - 6pm | Open || Open || Open || Open || style="background:green"| MicroCART |- ! 6pm - 7pm | Open || Open || Open || Open || style="background:green"| MicroCART |- ! 7pm - 8pm | Open || Open || Open || Open || style="background:green"| MicroCART |- ! 8pm - 9pm | Open || Open || Open || Open || style="background:green"| MicroCART |- ! 9pm - 10pm | Open || Open || Open || Open || style="background:green"| MicroCART |} == Getting Started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] 1a7d1131613cbd99b053d9009b588a75aabdd521 368 367 2017-09-18T22:30:44Z Rbuckley 12 wikitext text/x-wiki Welcome to the Distributed Autonomous and Networked Control Lab Wiki! Here you can find a wealth of information regarding the many projects we have running in the Lab. Below are some of the projects we are working on: ''' == Projects == ''' [[Crazyflie Swarm]] [[Robotic Agriculture Data Acquisition (RADA)]] [https://wikis.ece.iastate.edu/microcart-senior-design/index.php/Main_Page MicroCART] [[Camera System and VRPN]] ''' == Lab-Wide Information == [[Physical Parameters]] - Physical parameters for systems in the laboratory If you can't find what you're looking for please feel free to contribute. Consult the [http://meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Lab Schedule == {| class="wikitable" style="text-align:center" |+Reserved Lab Times |- ! width="130"|Time !! width="130"|Monday !! width="130"|Tuesday !! width="130"|Wednesday !! width="130"|Thursday !! width="130"|Friday |- ! 8am - 9am | Open || Open || Open || Open || Open |- ! 9am - 10am | Open || Open || Open || Open || Open |- ! 10am - 11am | Open || style="background:orange"|CrazyFlie || Open || Open || Open |- ! 11am - 12pm | Open || style="background:orange"|CrazyFlie || Open || Open || Open |- ! 12pm - 1pm | Open || style="background:orange"|CrazyFlie|| Open || style="background:orange"|CrazyFlie || Open |- ! 1pm - 2pm | Open || style="background:green"|MicroCART Meeting || style="background:orange"|CrazyFlie || style="background:orange"|CrazyFlie || Open |- ! 2pm - 3pm | Open || Open ||style="background:orange"|CrazyFlie || style="background:orange"|CrazyFlie || Open |- ! 3pm - 4pm | Open || Open || style="background:orange"|CrazyFlie || style="background:green"|MicroCART || Open |- ! 4pm - 5pm | style="background:orange"|CrazyFlie Meeting || style="background:teal"|RADA || style="background:teal"|RADA Meeting || style="background:green"|MicroCART || style="background:green"|MicroCART |- ! 5pm - 6pm | style="background:teal"|RADA || style="background:teal"|RADA || style="background:teal"|RADA || Open || style="background:green"|MicroCART |- ! 6pm - 7pm | style="background:teal"|RADA || style="background:teal"|RADA || style="background:teal"|RADA || Open || Open |- ! 7pm - 8pm | Open || Open || Open || Open || Open |- ! 8pm - 9pm | Open || Open || Open || Open || Open |- ! 9pm - 10pm | Open || Open || Open || Open || Open |} == Getting Started == * [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] 95f93bd1b5a3972912ed205e655f1f4020c78f06 Camera System and VRPN 0 84 358 2017-02-01T00:31:01Z Imciner2 6 Created page with " == Tracking Tools Software == === Resetting Orientation === The camera system Tracking Tools software includes a feature to "Reset Orientation" of the currently selected tr..." wikitext text/x-wiki == Tracking Tools Software == === Resetting Orientation === The camera system Tracking Tools software includes a feature to "Reset Orientation" of the currently selected trackable. This feature will only bias the angular position (basically subtract off the current values from the calculated angles), and will not rotate the coordinate system of the trackable to match the new orientation. '''This feature cannot be used to modify the coordinate system.''' e31583e940e9b02fdf95b36795f534d2605be8ce 359 358 2017-02-01T00:39:30Z Imciner2 6 /* Tracking Tools Software */ wikitext text/x-wiki == Tracking Tools Software == === Angular Display === The Tracking Tools software includes a display of the trackable's current position (X,Y,Z and attitude). The X, Y, Z values displayed are relative to the camera system's coordinate axis. The attitude displayed is in Euler Angles relative to the camera's coordinate system (its inertial frame). The sequence of Euler angles it uses to convert into these angles '''is not the Yaw-Pitch-Roll (Aerospace) sequence.''' === Resetting Orientation === The camera system Tracking Tools software includes a feature to "Reset Orientation" of the currently selected trackable. This feature will only bias the angular position (basically subtract off the current values from the calculated angles), and will not rotate the coordinate system of the trackable to match the new orientation. '''This feature cannot be used to modify the coordinate system.''' 1d5c136c676a20052577a8f3a7efe45b8d64ffa3 361 359 2017-04-24T20:36:10Z Imciner2 6 wikitext text/x-wiki == Calibrating The Cameras == === Setting the Ground Plane === == Tracking Tools Software == === Angular Display === The Tracking Tools software includes a display of the trackable's current position (X,Y,Z and attitude). The X, Y, Z values displayed are relative to the camera system's coordinate axis. The attitude displayed is in Euler Angles relative to the camera's coordinate system (its inertial frame). The sequence of Euler angles it uses to convert into these angles '''is not the Yaw-Pitch-Roll (Aerospace) sequence.''' === Resetting Orientation === The camera system Tracking Tools software includes a feature to "Reset Orientation" of the currently selected trackable. This feature will only bias the angular position (basically subtract off the current values from the calculated angles), and will not rotate the coordinate system of the trackable to match the new orientation. '''This feature cannot be used to modify the coordinate system.''' ece16d7e321be80198970e3c8fdf9f0ab5df2ce9 363 361 2017-04-24T20:47:17Z Imciner2 6 /* Setting the Ground Plane */ wikitext text/x-wiki == Calibrating The Cameras == === Setting the Ground Plane === In order to setup the axis system for the camera system, the ground plane tool needs to be used. It has 3 trackables on it, and form an L shape. The negative Z axis is marked by the arrow (so it is negative in that direction). The X axis is the other arm. To orient it, place it so that the short leg of the L faces east (towards the whiteboards), and the long leg pointing towards the ceiling. In order to get this oriented, it needs to be supported as shown in the image below. When aligning it, also use the level and make sure the long leg is perpendicular to the floor (it may be necessary to prop it up to make it perpendicular). Once the tool is set, select the three trackables in the software window. Then inside the "Ground Plane" tab, click on the "Set Ground Plane" button to create the axis system. [[File:CameraGroundPlane.jpg|300px|Ground plane configuration for the camera system]] == Tracking Tools Software == === Angular Display === The Tracking Tools software includes a display of the trackable's current position (X,Y,Z and attitude). The X, Y, Z values displayed are relative to the camera system's coordinate axis. The attitude displayed is in Euler Angles relative to the camera's coordinate system (its inertial frame). The sequence of Euler angles it uses to convert into these angles '''is not the Yaw-Pitch-Roll (Aerospace) sequence.''' === Resetting Orientation === The camera system Tracking Tools software includes a feature to "Reset Orientation" of the currently selected trackable. This feature will only bias the angular position (basically subtract off the current values from the calculated angles), and will not rotate the coordinate system of the trackable to match the new orientation. '''This feature cannot be used to modify the coordinate system.''' 73731c5d61fd40e5fb4a5d992628151124abc78c 364 363 2017-04-28T16:18:21Z Imciner2 6 wikitext text/x-wiki == Calibrating The Cameras == === Setting the Ground Plane === In order to setup the axis system for the camera system, the ground plane tool needs to be used. It has 3 trackables on it, and form an L shape. The negative Z axis is marked by the arrow (so it is negative in that direction). The X axis is the other arm. To orient it, place it so that the short leg of the L faces east (towards the whiteboards), and the long leg pointing towards the ceiling. In order to get this oriented, it needs to be supported as shown in the image below. When aligning it, also use the level and make sure the long leg is perpendicular to the floor (it may be necessary to prop it up to make it perpendicular). Once the tool is set, select the three trackables in the software window. Then inside the "Ground Plane" tab, click on the "Set Ground Plane" button to create the axis system. [[File:CameraGroundPlane.jpg|300px|Ground plane configuration for the camera system]] == Tracking Tools Software == === Angular Display === The Tracking Tools software includes a display of the trackable's current position (X,Y,Z and attitude). The X, Y, Z values displayed are relative to the camera system's coordinate axis. The attitude displayed is in Euler Angles relative to the camera's coordinate system (its inertial frame). The sequence of Euler angles it uses to convert into these angles '''is not the Yaw-Pitch-Roll (Aerospace) sequence.''' === Resetting Orientation === The camera system Tracking Tools software includes a feature to "Reset Orientation" of the currently selected trackable. This feature will only bias the angular position (basically subtract off the current values from the calculated angles), and will not rotate the coordinate system of the trackable to match the new orientation. '''This feature cannot be used to modify the coordinate system.''' == Computer Configuration == === Windows Settings === It appears that Tracking Tools has an incompatibility with some updates provided with Windows 7. The problem is the VRPN server is unable to consistently maintain an update interval of 10ms position packets (the software still gets position at 10ms intervals, but it is not reported over VRPN at that rate). To fix this, the Tracking Tools software must be run on a non-updated version of Windows 7 (it appears updates released sometime in 2015-2016 broke the VRPN function). So Windows Update should be disabled. Additionally, system restore should be enabled (for both settings and files), so that in the future if anything happens the system can be reverted to a known-working state. ef785413ccce88cb40e1115b7d46090777b132c6 365 364 2017-04-28T16:20:11Z Imciner2 6 wikitext text/x-wiki == System Overview == The VRPN system operates on IP address 192.168.0.120 port 3883/ == Calibrating The Cameras == === Setting the Ground Plane === In order to setup the axis system for the camera system, the ground plane tool needs to be used. It has 3 trackables on it, and form an L shape. The negative Z axis is marked by the arrow (so it is negative in that direction). The X axis is the other arm. To orient it, place it so that the short leg of the L faces east (towards the whiteboards), and the long leg pointing towards the ceiling. In order to get this oriented, it needs to be supported as shown in the image below. When aligning it, also use the level and make sure the long leg is perpendicular to the floor (it may be necessary to prop it up to make it perpendicular). Once the tool is set, select the three trackables in the software window. Then inside the "Ground Plane" tab, click on the "Set Ground Plane" button to create the axis system. [[File:CameraGroundPlane.jpg|300px|Ground plane configuration for the camera system]] == Tracking Tools Software == === Angular Display === The Tracking Tools software includes a display of the trackable's current position (X,Y,Z and attitude). The X, Y, Z values displayed are relative to the camera system's coordinate axis. The attitude displayed is in Euler Angles relative to the camera's coordinate system (its inertial frame). The sequence of Euler angles it uses to convert into these angles '''is not the Yaw-Pitch-Roll (Aerospace) sequence.''' === Resetting Orientation === The camera system Tracking Tools software includes a feature to "Reset Orientation" of the currently selected trackable. This feature will only bias the angular position (basically subtract off the current values from the calculated angles), and will not rotate the coordinate system of the trackable to match the new orientation. '''This feature cannot be used to modify the coordinate system.''' == Computer Configuration == === Windows Settings === It appears that Tracking Tools has an incompatibility with some updates provided with Windows 7. The problem is the VRPN server is unable to consistently maintain an update interval of 10ms position packets (the software still gets position at 10ms intervals, but it is not reported over VRPN at that rate). To fix this, the Tracking Tools software must be run on a non-updated version of Windows 7 (it appears updates released sometime in 2015-2016 broke the VRPN function). So Windows Update should be disabled. Additionally, system restore should be enabled (for both settings and files), so that in the future if anything happens the system can be reverted to a known-working state. === Firewall Settings === The Windows computer hosting the VRPN server must have port 3883 both TCP and UDP protocols opened in order to work. Additionally, all clients should have those two ports opened as well. Since VRPN appears to create connections in both directions. 82327bd0d817d8c27b49cf134ef8367621f25207 File:CameraGroundPlane.jpg 6 85 362 2017-04-24T20:37:58Z Imciner2 6 Ground plane orientation for the camera system calibration. wikitext text/x-wiki Ground plane orientation for the camera system calibration. bce94eb616b22f6d3c56ecb710d7b984f97d3874